I want to search through my xml file. The structure looks like this:
<AForetag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Place ID="1006">
<Foretag>
<Epost>info#abc123.se</Epost>
<Namn>Abe</Namn>
<Ort>Abc123</Ort>
<Adress>Abc123</Adress>
<Postnummer>Abc123</Postnummer>
<Landskap>Abc123</Landskap>
<Telefon>Abc123</Telefon>
<Medlemskap>Abc123</Medlemskap>
</Foretag>
<Foretag>
<Epost>def456</Epost>
<Namn>def456</Namn>
<Ort>def456</Ort>
<Adress>def456</Adress>
<Postnummer>def456</Postnummer>
<Landskap>def456</Landskap>
<Telefon>def456</Telefon>
<Medlemskap>def456</Medlemskap>
</Foretag>
</Place>
</Aforetag>
And I want to search for the Element <Landskap>. And if I get and match I should pick all the other elements, Epost, Namn, Ort, Adress, Postnummer, Landskap, Telefon and Medlemskap. The info I want to put in an array.
I have tried this:
var aforetag = from foretag in doc.Descendants("Place")
where foretag.Attribute("ID").Value == "1006"
select foretag;
var landskap = aforetag.Elements("Foretag")
.Descendants()
.Where(x => x.Element("Landskap")
.Value
.Contains(s)
.Descendants()
.Select(c => (string)c)
.ToArray();
Your code is not well formed. Copy this into VS and there are a few errors, fix one and more errors!...
And most importantly, your XML is not XML as the start and end tag don't even match! Plus, there are other issues.
Fix all these and I'm sure it will help.
var landskap = aforetag.Elements("Foretag")
.Where(e=>e.Element("Landskap").Value.Contains(s))
.Select(e=>e.Elements().Select(x=>x.Value).ToArray());
//the result is an IEnumerable<string[]> for the matched keyword s
Related
Since I am not very familiar with LINQ and xDocument, I struggle to implement the following:
I have a XML file which looks like
<document>
<attribut1/>
<attribut2>
<house price="100" location="UK" id-ext="Id-100"/>
<house price="300" location="GB" id-int="Id-101"/>
</attribut2>
<attribut3/>
</document>
Speaking in Pseudo Code I need something like
Input: xDocument
Output: List containing strings with all values, i.e. "Id-100" in this example, of those attributes where "id-ext" was included in the attribut name. Hence, I try to get the values of those attributes which contain some certain letters in their name.
I already searched for similar suggestions like the one stated here:
How to search entire XML file for keyword?
But the point is that here the whole XML-Node is returned and I don't manage to break it down to the name of an attribute.
I would appreciate any suggestions of how to move one after applying "Descendants" to get the values of those attributs where some keywords are contained in the attribut name.
Use a dictionary
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, List<XElement>> dict = doc.Descendants("house")
.Where(x => x.Attribute("id-ext") != null)
.GroupBy(x => (string)x.Attribute("id-ext"))
.ToDictionary(x => x.Key, y => y.ToList());
Assuming "keywords are contained in the attribut name" means that the attribute name as a string contains a specific substring, and that this attribute may occur on any element in the document:
var doc = XDocument.Parse(#"<document>
<attribut1/>
<attribut2>
<house price='100' location='UK' id-ext='Id-100'/>
<house price='300' location='GB' id-int='Id-101'/>
</attribut2>
<attribut3/>
</document>");
foreach (var s in doc
.Descendants()
.SelectMany(e => e.Attributes())
.Where(a => a.Name.LocalName.Contains("id-ext"))
.Select(a => a.Value))
{
Console.WriteLine(s);
}
I have to write a program using Linq. I'm just a student and I didn't learned that yet, so I have two questions:
What would be a good book/ebook... to teach myself what my next question will be about?
I have an XML-File, that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Projects>
<Project>
<Information>
<Name>Project1</Name>
<Date>26.01.2015</Date>
</Information>
<Files ID = "S" path = "C:\Users\marcel\Documents">
<file>Test1.txt</file>
<file>Test2.txt</file>
<file>Test3.txt</file>
<file>Test4.txt</file>
<file>Test5.txt</file>
</Files>
<Files ID = "C" path = "C:\Users\marcel\Documents">
<file>Test1(1).txt</file>
<file>Test1(2).txt</file>
<file>Test1(3).txt</file>
<file>Test1(4).txt</file>
<file>Test1(5).txt</file>
</Files>
</Project>
I want to get a string-array which is containing the values of the "file" elements, depenging on ID=S or C.
I have more than 1 project in there, so it first has to be searched by name, that's working right now:
var entries = from items in xelement.Elements("Project")
where (string)items.Element("Name").Value == projectName
select items;
that gets me the whole block of the needed project.
Can I use the result of the first command for getting the filenames?
Or can I just extend the code of the first part?
To get a specific Project element having the specified name you can use First:
var projectElement = xElement
.Elements("Project")
.First(x => (String) x.Element("Information").Element("Name").Value == projectName);
In a similar way you can find the desired Files element by specifying a value for the ID attribute:
var filesElement = projectElement
.Elements("Files")
.First(x => x.Attribute("ID").Value == id);
You can then use Select to project the File elements to their values and convert that to an array:
var files = filesElement
.Elements("file")
.Select(x => (String) x.Value)
.ToArray();
Note that this code will throw exceptions if the XML has an unexpected format. E.g., if First does not find a matching element an exception is thrown. Also, the Element method will return null if the specified element is not found and thus code like x.Element("Information").Element("Name") will throw an exception if there is no Information element because the next call to Element is performed on the null reference.
Thank you Martin, that worked :)
I just came up with an own solution looking like this:
var files = from file in entries.Elements("Files").Elements("file")
where (string)file.Parent.Attribute("ID").Value == cOrS
select file.Value;
I have a following xml file. I need to change the inner text of ANY tag, which contains the value «Museum», or just a tag for a start:
<src>
<riga>
<com>¾</com>
<riquadro797>Direction to move</riquadro797>
</riga>
<riga>
<llt>
<com>Museum</com>
<elemento797>Direction not to move</elemento797>
</llt>
</riga>
<operation>
<com> </com>
<riquadro797>Museum</riquadro797>
</operation>
<riga>
<gt>
<elemento797>Direction not to move</elemento797>
</gt>
</riga>
</src>
I've parsed this file to XElement. What I've tried and it dos not work:
var tt = xmlCluster.Elements(First(x => x.Value == "Museum");
This code is not proper, as I cannot predict which element will contain "Museum":
var el = rootElRecDocXml.SelectSingleNode("src/riga/gt/elemento797[text()='"+mFilePath+"']");
How to do it? Any help will be greatly appreciated!
just grab all elements with Museum values:
var doc = XDocument.Parse(xml);
var elements = doc.Descendants().Where(e => e.Value == "Museum");
foreach (var ele in elements)
ele.Value = "Test";
//doc is updated with new values
as Selman22 noted, doc will just be a working copy of your xml. You'll need to call doc.Save to apply anything back to the disk, or wherever you need
Elements() only looks at a single level in the heirarchy. I think you want Descendants() instead...
If you want an older-school XPath option, you need to do a global search on the tree - you can use the // XPath expression for this:
var els = rootElRecDocXml.SelectNodes("//[text()='"+mFilePath+"']");
I want to read a xml file using Linq. This xml file is composed of 1 header and N Sub-Elements like this :
<rootNode>
<header>
<company name="Dexter Corp." />
</header>
<elements>
<element>one</element>
<element>eleven</element>
<element>three</element>
<element>four</element>
<element>five</element>
<element>three</element>
<element>two</element>
<element>two</element>
</elements>
</rootNode>
I want to retrieve elements which are a value (example : two). And only if I retrieve elements, I get the header elements.
Today, I do like this :
string xmlFilePath = #"C:\numbers.xml";
XDocument doc = XDocument.Load(xmlFilePath);
var header = doc.Descendants().Elements("header");
var elements = doc.Descendants()
.Elements("elements")
.Elements("element")
.Where(el => el.Value == "two");
// I get this values even if there is no 'elements'
string companyName = header.Descendants("company").Attributes("name").Single().Value;
string serialNumber = header.Descendants("serial").Single().Value;
return elements.Select(el => new {Company = companyName, Serial = serialNumber, Value = el.Value});
Is there a better way to parse the file ? (and increase performance ?)
If performance is important to you, you shouldn't use doc.Descendants() to look for an element at some known location. It always scans the whole document, which is slow if the document is big.
Instead, do something like
doc.Root.Element("header")
or
doc.Root.Element("elements")
.Elements("element")
.Where(el => el.Value == "two")
That should be much faster.
I have an xml doc defined as
<Body>Stuff stuff stuff <FormatStuff> alsdkfafkafkaf </FormatStuff> </Body>
Now, this is apparently valid xml (which I wouldn't have guessed). I want to return just the information in Body, and a separate XElement for <FormatStuff>, so it would look like
Stuff, Stuff, Stuff
alsdkfafkafkaf
the .Value of the Body xelement obviously returns everything. Thanks for any help.
Why wouldn't you have guessed that this was valid XML? It's not really clear what you want, to be honest. If you just want to get the text nodes for the Body element, you can use:
var textNodes = body.DescendantNodes()
.OfType<XText>()
If you want to get the value of all those nodes concatenated together, you'd do something like:
var text = string.Join("", body.DescendantNodes()
.OfType<XText>()
.Select(x => x.Value)
.ToArray());
(You could use the node type, but then you just have an IEnumerable<XNode> which isn't as useful, as I found out when trying to compile the above :)
You can get the FormatStuff element with body.Element("FormatStuff").