Hi Not sure if this can be done but I know someone here will know :)
using
XElement oNodeEquip = xmlDoc.XPathSelectElement("//ItemAry/Item/Equip");
how would I select Equip from the second in the following:
<TestInfo>
<ItemAry>
<Item>
<testData>ABC</testData>
</Item>
<Item>
<testData>XYZ</testData>
<Equip>xxx</Equip>
</Item>
</ItemAry>
</TestInfo>
there will always be at lease 2 <Item> and the node I want the value from will always be in the second <Item>
this is a WPF app using .Net 4.0
Try this XPath expression:
//ItemAry/Item[2]/Equip
It considers only the second <Item> element.
You can easily do it with Linq to Xml:
XDocument xdoc = XDocument.Load(path_to_xml);
var second = (string)xdoc.Descendants("Item").Skip(1).Element("Equip");
Use:
(/*/ItemAry/Item)[2]/Equip
The currently selected answer can produce unexpected results, depending on the specific XML document at hand:
//ItemAry/Item[2]/Equip
selects the Equip children of all Item elements that are the second Item child of their ItemAry parent.
So, if the source XML document is:
<TestInfo>
<ItemAry>
<Item>
<testData>ABC</testData>
</Item>
<Item>
<testData>XYZ</testData>
<Equip>xxx</Equip>
</Item>
</ItemAry>
<ItemAry>
<Item>
<testData>DEF</testData>
</Item>
<Item>
<testData>TUW</testData>
<Equip>yyy</Equip>
</Item>
</ItemAry>
</TestInfo>
the above potentially-wrong expression selects two elements:
<Equip>xxx</Equip>
<Equip>yyy</Equip>
The correct expression provided in this answer:
(/*/ItemAry/Item)[2]/Equip
selects just:
<Equip>xxx</Equip>
If you are ceratin about position of the node, you can use position() function in your XPath:
XElement oNodeEquip = xmlDoc.XPathSelectElement("//ItemAry/Item[position()=2]/Equip");
Related
I am trying to convert the below xml
<variants>
<item>
<name>sport</name>
<description>sport desc</description>
<item-values>
<item-value>
<item>ball</item>
<value>stichball</value>
</item-value>
</item-values>
</item>
</variants>
to xml like below as the nodes splitted to key value pair
<variants>
<item name="sport" description="sport desc">
<item-values>
<item-value item="ball" value="stichball"/>
</item-values>
</item>
</variants>
Is it possible to make this in a generic way
This question already has an answer here:
Deserializing into a List without a container element in XML
(1 answer)
Closed 2 years ago.
In .NET Coew 3.1 I am trying to generate an XML file of the following class, but without the orders tag showing in the XML file, meaning I have the root tag, than only the list of items
[XmlRoot("data")]
public class PurchaseOrder
{
[XmlElement("orders")]
public Item [] ItemsOrders;
}
[XmlRoot("item")]
public class Item
{
[XmlElement("itemid")]
public string ItemID;
[XmlElement("price")]
public decimal ItemPrice;
}
would result in
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<orders>
<item>
<itemid>aaa111</itemid>
<ItemPrice>34.22</ItemPrice>
</item>
<item>
<itemid>bbb222</itemid>
<price>2.89</price>
</item>
</orders>
</data>
but I need to remove the orders tag. The result I need to produce is
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<item>
<itemid>aaa111</itemid>
<ItemPrice>34.22</ItemPrice>
</item>
<item>
<itemid>bbb222</itemid>
<price>2.89</price>
</item>
</data>
The best way to get the correct classes you require would be to copy the XML you want to the clipboard, and then (in VS2019) Edit/Paste Special/Paste Classes As XML.
This will create the correct classes for the XML you supplied.
I have the following XML which I want to order by priority. Don't fancy using XPath and thought LINQ might work but I get an argument exception thrown with the message "At least one object must implement IComparable."
Can I order the results somehow?
<Root>
<Item>
<Priority><![CDATA[4]]</Priority>
</Item>
<Item>
<Priority><![CDATA[1]]</Priority>
</Item>
<Item>
<Priority><![CDATA[3]]</Priority>
</Item>
</Root>
var result = doc.SelectNodes("//Item");
var ordered = ddddd.Cast<XmlNode>().OrderBy(x => x.SelectSingleNode("Priority")); //EXCEPTION!!!
Change x => x.SelectSingleNode("Priority") to x => x.SelectSingleNode("Priority").InnerText
Oh, and remember, that you will compare strings, not ints, that way.
I've chosen the title here as my problem is I need to get the Item nodes mentioned in the example.
I have the following XML and am having problems using LINQ to query it, I've been able to parse XML before - however I've been stuck on this for hours and hope someone can help.
Here is my XML data below (example data):
<a:entry
xmlns:a="http://www.w3.org/2005/Atom">
<a:id>98765</a:id>
<info>Data Catalogue</info>
<data>
<items>
<item>
<id>123456</id>
<value>Item One</value>
</item>
<item>
<id>654321</id>
<value>Item Two</value>
</item>
</items>
</data>
<items>
<item>
<id>123456</id>
<value>Item One</value>
</item>
<item>
<id>654321</id>
<value>Item Two</value>
</item>
</items>
<a:author>
<a:name>Catalogue</a:name>
</a:author>
</a:entry>
I want to be able to extract the ID from the Item XML tag under Items, however there is an Items Tag with Item entries under data I DO NOT want these nodes at all - I want root/items/id/id if this were expressed as path. I've tried everything I know with LINQ so if someone could help, things to note although this is sample data it is based on the system - the format cannot be changed so that is not an acceptable solution.
I can't seem to determine where I'm going wrong - every LINQ expression I try returns nothing, I think the namespace is an issue and have tried to integrate this but I'm going in circles.
Solution must work in Silverlight and C#
I have tried the following:
IEnumerable<XElement> nodes =
element.Elements().Where(e => e.Name.LocalName == "items")
However this gets me all the "items" including the ones under "data" I don't want those.
If I do the following on my XML I do see the Names of the Elements displayed:
XElement element = XElement.Parse(data);
foreach (XElement node in element.Elements())
{
MessageBox.Show(node.Name.LocalName);
}
However when I do this I cannot see the node names under items at all - I've checked the XElement and it does have the node and when I output the names above it "items" shows up along with info and id!
foreach (XElement node in element.Elements("items"))
{
MessageBox.Show(node.Name.LocalName);
}
Assuming element is your <a:entry> element:
var ids = element.Element("items")
.Elements("item")
.Select(item => item.Element("id").Value);
The Element and Elements methods return only direct children, not all descendants, so it doesn't return the <items> element which is under <data>
I had a blank Namespace Declaration in my XML I hadn't noticed once I added this into my code it worked - forgot LINQ is very NameSpace oriented!
XNamespace ns = "http://example.org/namespace";
var ids = element.Element(ns + "items")
.Elements("item")
.Select(item => item.Element("id").Value);
I have been trying to parse this xml in c#
<schema uri=http://blah.com/schema >
<itemGroups>
<itemGroup description="itemGroup1 label="itemGroup1">
<items>
<item description="The best" itemId="1" label="Nutella"/>
<item description="The worst" itemId="2" label="Vegemite"/>
</items>
</itemGroup>
</itemGroups>
</schema>
\itemGroup1\Nutella-The best
\itemGroup1\Vegemite-The worst
Any help or direction would be appreciated.
XDocument xDoc = XDocument.Load(myXml); //load your XML from file or stream
var rows = xDoc.Descendants("item").Select(x => string.Format(
#"\{0}-{1}\{2}-{3}",
x.Ancestors("itemGroup").First().Attribute("description").Value,
x.Ancestors("itemGroup").First().Attribute("label").Value,
x.Attribute("label").Value,
x.Attribute("description").Value));
Let's break down what we're doing:
xDoc.Descendants("item") gets us all <item> elements in the entire document
Select(x => string.Format(format, args) projects each <item> we got from the last operation into whatever format we specify in the lambda. In this case, a formatted string.
In terms of the XML tree, we're "sitting at" the <item> level, so we need to roll back up the tree to get the data for the parent group using Ancestors. Since that method returns a sequence of elements, we know we want the first (nearest to us) so we can read its attribute.
Now you have an IEnumerable<string>, one for each <item> in your XML document and the information in the format you specified:
foreach(string row in rows)
{
Console.WriteLine(row);
}