Lets say I have the following xml (a quick example)
<rows>
<row>
<name>one</name>
</row>
<row>
<name>two</name>
</row>
</rows>
I am trying to parse this by using XmlDocument and XPath (ultimately so I can make a list of rows).
For example...
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("//row"))
{
string rowName = row.SelectSingleNode("//name").InnerText;
}
Why, within my foreach loop, is rowName always "one"? I am expecting it to be "one" on the first iteration and "two" on the second.
It seems that //name gets the first instance in the document, rather than the first instance in the row as I would expect. After all, I am calling the method on the "row" node. If this is "just how it works" then can anybody please explain how I could change it to work to my needs?
Thank you
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("//row"))
{
var rowName = row.SelectSingleNode("name");
}
Is the code you posted actually correct? I get a compile error on row.SelectNode() as it isn't a member of XmlNode.
Anyway, my example above works, but assumes only a single <name>
node within the <row>
node so you may need to use SelectNodes()
instead of SelectSingleNode()
if that is not the case.
As others have shown, use .InnerText
to get just the value.
Use LINQ to XML. Include using System.Xml.Linq;
in your code file and then do the following code to get your list
XDocument xDoc = XDocument.Load(filepath);
IEnumerable<XElement> xNames;
xNames = xDoc.Descendants("name");
That will give you a list of the name elements. Then if you want to turn that into a List<string>
just do this:
List<string> list = new List<string>();
foreach (XElement element in xNames)
{
list.Add(element.value);
}
Your second xpath starts with //
. This is an abbreviation for /descendant-or-self::node()
, which you can see starts with /
, meaning it searches from the root of the document, whatever the context in which you use it.
You probably want one of:
var rowName = row.SelectSingleNode("name");
to find the name
nodes that are immediate children of the row
, or
var rowName = row.SelectSingleNode(".//name");
to find name
nodes *anywhere underthe
row. Note the
.` in this second xpath that causes the xpath to start from the context node.
Use a relative path e.g. string rowName = row.SelectSingleNode("name").InnerText;
.
The problem is in your second XPath query:
//row
This has a global scope, so no matter where you call it from, it will select all row
elements.
It should work if you replace your expression with:
.//row
I would use SelectSingleNode, and then the InnerText property.
var rowName = row.SelectSingleNode("name").InnerText;
Use the following
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("/rows/row"))
{
string rowName = row.SelectSingleNode("//name").InnerText.ToString();
}
来源:https://stackoverflow.com/questions/8299069/using-xpath-to-parse-an-xml-document