I have 2 XML Files and I want to get all the XNodes , which are in both files, only based on their same Attribute "id".
This is how an XML File looks like:
<parameters>
<item id="57">
<länge>8</länge>
<wert>0</wert>
</item>
<item id="4">
<länge>8</länge>
<wert>0</wert>
</item>
<item id="60">
<länge>8</länge>
<wert>0</wert>
</item>
</parameters>
Given a second XML File which looks like this:
<parameters>
<item id="57">
<länge>16</länge>
<wert>10</wert>
</item>
<item id="144">
<länge>16</länge>
<wert>10</wert>
</item>
</parameters>
Now I only want the XNode with the ID=57, since it is available in both files. So the output should look like this:
<item id="57">
<länge>8</länge>
<wert>0</wert>
</item>
I already did intersect both files like this:
aDoc = XDocument.Load(file);
bDoc = XDocument.Load(tmpFile);
intersectionOfFiles = aDoc.Descendants("item")
.Cast<XNode>()
.Intersect(bDoc.Descendants("item")
.Cast<XNode>(), new XNodeEqualityComparer());
This only seems to work, when all the descendant Nodes are the same. If some value is different, it won't work. But I need to get this to work on the same Attributes, the values or the descendants doesn't matter.
I also tried to get to the Attributes and intersect them, but this didn't work either:
intersectionOfFiles = tmpDoc
.Descendants(XName.Get("item"))
.Attributes()
.ToList()
.Intersect(fileDoc.Descendants(XName.Get("item")).Attributes()).ToList();
Am I missing something or is this a completely wrong approach?
Thanks in advance.
You should create your own IEqualityComparer that compares XML attributes you want:
public class EqualityComparerItem : IEqualityComparer<XElement>
{
public bool Equals(XElement x, XElement y)
{
return x.Attribute("id").Value == y.Attribute("id").Value;
}
public int GetHashCode(XElement obj)
{
return obj.Attribute("id").Value.GetHashCode();
}
}
which you would then pass to XML parsing code:
var intersectionOfFiles = aDoc.Root
.Elements("item")
.Intersect(
bDoc.Root
.Elements("item"), new EqualityComparerItem());
I also changed some parts of your XML parsing code (XElement instead of XNode since "item" is XML element and "id" is XML attribute).
I'm getting a JsonSerializationException calling DeserializeXmlNode() on JSON data that starts with [[ (i.e. it's an array of arrays).
What is the best
way to turn this into XML?
Are there any other JSON schemas that can't be turned into XML?
Update: How the XML should appear is an interesting question. Having an array of arrays means there is no root node (that's an easy one - insert ) but also the set of children nodes have no name. I'm not sure what makes sense here. And this may be a deal killer for using XPath on JSON. So on this part too, any suggestions?
Update 2 - the JSON data:
[["P0010001","NAME","state"],
["4779736","Alabama","01"],
["710231","Alaska","02"],
["6392017","Arizona","04"],
["2915918","Arkansas","05"],
["37253956","California","06"],
["5029196","Colorado","08"],
["3574097","Connecticut","09"],
["897934","Delaware","10"],
["601723","District of Columbia","11"],
["18801310","Florida","12"],
["9687653","Georgia","13"],
["1360301","Hawaii","15"],
["1567582","Idaho","16"],
["12830632","Illinois","17"],
["6483802","Indiana","18"],
["3046355","Iowa","19"],
["2853118","Kansas","20"],
["4339367","Kentucky","21"],
["4533372","Louisiana","22"],
["1328361","Maine","23"],
["5773552","Maryland","24"],
["6547629","Massachusetts","25"],
["9883640","Michigan","26"],
["5303925","Minnesota","27"],
["2967297","Mississippi","28"],
["5988927","Missouri","29"],
["989415","Montana","30"],
["1826341","Nebraska","31"],
["2700551","Nevada","32"],
["1316470","New Hampshire","33"],
["8791894","New Jersey","34"],
["2059179","New Mexico","35"],
["19378102","New York","36"],
["9535483","North Carolina","37"],
["672591","North Dakota","38"],
["11536504","Ohio","39"],
["3751351","Oklahoma","40"],
["3831074","Oregon","41"],
["12702379","Pennsylvania","42"],
["1052567","Rhode Island","44"],
["4625364","South Carolina","45"],
["814180","South Dakota","46"],
["6346105","Tennessee","47"],
["25145561","Texas","48"],
["2763885","Utah","49"],
["625741","Vermont","50"],
["8001024","Virginia","51"],
["6724540","Washington","53"],
["1852994","West Virginia","54"],
["5686986","Wisconsin","55"],
["563626","Wyoming","56"],
["3725789","Puerto Rico","72"]]
I had an array of objects, shaped like:
[{foo:bar}, {foo:bar2}]
...What I did to work around this problem is to wrap the text first like so:
public XmlDocument JsonArrayToXml(string json)
{
var wrappedDocument = string.Format("{{ item: {0} }}", json);
var xDocument = JsonConvert.DeserializeXmlNode(wrappedDocument, "collection");
return xDocument;
}
This does not throw an error. The shape of the XML resembles:
<?xml version="1.0" encoding="UTF-8"?>
<collection>
<item>
<foo>bar</foo>
</item>
<item>
<foo>bar2</foo>
</item>
</collection>
I'm trying to populate an array with the following xml:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<data>
<item>
<date>1307018090</date>
<price>10.4718867</price>
<low>10.38100000</low>
<high>10.49000000</high>
<nicedate>14:39</nicedate>
</item>
<item>
...
</item>
and so on
I'm using this Linq-query, which to me means that It'll create one object per :
var items = from item in doc.Element("data").Descendants()
select new Currency
{
Close = item.Element("price").Value.ToString(),
Date = item.Element("date").Value.ToString(),
Low = item.Element("low").Value.ToString(),
High = item.Element("high").Value.ToString(),
Time = item.Element("nicedate").Value.ToString()
};
And when I foreach through items, only one item gets selected. I'm not very used to Linq so I can't figure out how to properly construct this statement. Any suggestions?
You need to start the Linq-Xml like so
var items =
from item in
doc.Element("data")
.Elements("item")
Descedants() method returns not only children, but also grand-children, grand-grand-children etc. So, the second tag that gets processed by LINQ is your first <item>'s <date> and it isn't processed (I think there should be an exception here, can't check at the moment).
Replace your Descedants() call to Elements("item"), as suggested by #DaveShaw
I am new to XML and Linq to XML and I just can't find a good guide that explains how to work with it. I have a simple XML string structured as follows
<mainitem>
<items>
<itemdescription>ABC</itemdescription>
<item>
<itemtext>XXX</itemtext>
</item>
<item>
<itemtext>YYY</itemtext>
</item>
<item>
<itemtext>ZZZ</itemtext>
</item>
</items>
<overalldescription>ABCDEFG</overalldescription>
<itemnodes>
<node caption="XXX" image="XXX"></node>
<node caption="YYY" image="YYY"></node>
<node caption="ZZZ" image="ZZZ"></node>
</itemnodes>
</mainitem>
I am using C# code like
var Items = (from xElem in XMLCODEABOVE.Descendants("item")
select new ItemObject
{
ItemObjectStringProperty = xElem.Element("itemtext").Value,
}
);
to extract a list of the itemtext objects for use with my code. Where I need help is in extracting a list of the caption and image attributes of my node elements. I also need the overalldescription and the itemdescription. I have tried every variation of the above code substituting Descendant for Elements, Element for Attribute etc. I know this is probably a basic question but there doesn't seem to be a straight forward guide out there to explain this to a beginner.
To get the captions
// IEnumerable<string>
var captions = from node in doc.Descendants("node")
select node.Attribute("caption").Value;
Or both the captions and image attributes in one shot:
// IEnumerable of the anonymous type
var captions = from node in doc.Descendants("node")
select new {
caption = node.Attribute("caption").Value,
image = node.Attribute("image").Value
};
For the descriptions:
// null ref risk if element doesn't exist
var itemDesc = doc.Descendants("itemdescription").FirstOrDefault().Value;
var overallDesc = doc.Descendants("overalldescription ").FirstOrDefault().Value;
I have an XML document looking similar to this:
<items>
<item cat="1" owner="14">bla</item>
<item cat="1" owner="9">bla</item>
<item cat="1" owner="14">bla</item>
<item cat="2" owner="12">bla</item>
<item cat="2" owner="12">bla</item>
</items>
Now I'd like to get all unique owners (I actually only need the attribute value of the owner) belonging to a specified category using a linq query. In my example, the query for cat 1 would return a list containing 9 and 14. How can I do that? Linq syntax would be preferred over Lambdas. Thanks in advance ;)
Presuming the fragment is in itemsElement:
var distinctOwners = (from item in itemsElement.Element("item")
where itemElements.Attribute("cat") == 1
select item.Attribute("owner")).Distinct();
Apologies for formatting and indentation!
Try this function:-
static IEnumerable<int> GetOwners(XDocument doc, string cat)
{
return from item in doc.Descendants("item")
where item.Attribute("cat").Value == cat
select (int)item.Attribute("owner")).Distinct();
}
XElement ele = XElement.Parse(#"<items><item cat=""1"" owner=""14"">bla</item><item cat=""1"" owner=""9"">bla</item>" +
#"<item cat=""1"" owner=""14"">bla</item><item cat=""2"" owner=""12"">bla</item>" +
#"<item cat=""2"" owner=""12"">bla</item></items>");
int cat = 1;
List<int> owners = ele.Elements("item")
.Where(x=>x.Attribute("cat").Value==cat.ToString()).Select(x=>Convert.ToInt32(x.Attribute("owner").Value)).Distinct().ToList();