可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答1:
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.
回答2:
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);
}
回答3:
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.
回答4:
Use a relative path e.g. string rowName = row.SelectSingleNode("name").InnerText;
.
回答5:
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
回答6:
I would use SelectSingleNode, and then the InnerText property.
var rowName = row.SelectSingleNode("name").InnerText;
回答7:
Use the following
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("/rows/row"))
{
string rowName = row.SelectSingleNode("//name").InnerText.ToString();
}