简体   繁体   English

使用XPath解析XML文档

[英]Using XPath to parse an XML document

Lets say I have the following xml (a quick example) 可以说我有以下xml(一个简单的例子)

<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). 我试图通过使用XmlDocument和XPath解析这个(最终我可以创建行列表)。

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"? 为什么,在我的foreach循环中,rowName总是“一个”? 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. 似乎// name获取文档中的第一个实例,而不是我期望的行中的第一个实例。 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. 我在row.SelectNode()上遇到编译错误,因为它不是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. 无论如何,我上面的示例有效,但假设<row>节点中只有一个<name>节点,因此如果不是这样,您可能需要使用SelectNodes()而不是SelectSingleNode()

As others have shown, use .InnerText to get just the value. 正如其他人所示,使用.InnerText来获取值。

Use LINQ to XML. 使用LINQ to XML。 Include using System.Xml.Linq; 包括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<string> list = new List<string>();
foreach (XElement element in xNames)
{
    list.Add(element.value);
}

Your second xpath starts with // . 你的第二个xpath以//开头。 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. 这是/descendant-or-self::node()的缩写,您可以看到以/开头,这意味着它从文档的根目录搜索,无论您使用它的上下文。

You probably want one of: 你可能想要一个:

var rowName = row.SelectSingleNode("name");

to find the name nodes that are immediate children of the row , or 找到该row 直接子节点的name节点,或

var rowName = row.SelectSingleNode(".//name");

to find name nodes *anywhere under the row . Note the 在行下the任何位置查找name节点* . Note the . Note the .` in this second xpath that causes the xpath to start from the context node. . Note the第二个xpath中. Note the .`,它导致xpath从上下文节点开始。

Use a relative path eg string rowName = row.SelectSingleNode("name").InnerText; 使用相对路径,例如string rowName = row.SelectSingleNode("name").InnerText; .

The problem is in your second XPath query: 问题出在第二个XPath查询中:

//row

This has a global scope, so no matter where you call it from, it will select all row elements. 这具有全局范围,因此无论您从何处调用它,它都将选择所有 row元素。

It should work if you replace your expression with: 如果用以下代码替换表达式,它应该有效:

.//row

我会使用SelectSingleNode,然后使用InnerText属性。

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();
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM