使用 XPath 解析 XML 文档

问题描述 投票:0回答:8

假设我有以下 xml(一个简单的示例)

<rows>
   <row>
      <name>one</name>
   </row>
   <row>
      <name>two</name>
   </row>
</rows>

我尝试使用 XmlDocument 和 XPath 来解析它(最终我可以制作一个行列表)。

例如...

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

foreach(XmlNode row in doc.SelectNodes("//row"))
{
   string rowName = row.SelectSingleNode("//name").InnerText;
}

为什么在我的 foreach 循环中, rowName 始终为“一”?我希望第一次迭代时它是“一”,第二次迭代时是“二”。

//name 似乎获取了文档中的第一个实例,而不是我所期望的行中的第一个实例。毕竟,我是在“行”节点上调用该方法。如果这就是“它是如何工作的”,那么任何人都可以解释一下我如何改变它以满足我的需要吗?

谢谢你

c# xpath xmldocument
8个回答
18
投票
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

foreach(XmlNode row in doc.SelectNodes("//row"))
{
   var rowName = row.SelectSingleNode("name");
}

您发布的代码真的正确吗?我在 row.SelectNode() 上遇到编译错误,因为它不是 XmlNode 的成员。

无论如何,我上面的示例是有效的,但假设

<name>
节点中只有一个
<row>
节点,因此如果情况并非如此,您可能需要使用
SelectNodes()
而不是
SelectSingleNode()

正如其他人所示,使用

.InnerText
即可获取值。


5
投票

使用 LINQ to XML。在您的代码文件中包含

using System.Xml.Linq;
,然后执行以下代码来获取您的列表

XDocument xDoc = XDocument.Load(filepath);
IEnumerable<XElement> xNames;

xNames = xDoc.Descendants("name");

这将为您提供名称元素的列表。然后如果你想把它变成

List<string>
只需这样做:

List<string> list = new List<string>();
foreach (XElement element in xNames)
{
    list.Add(element.value);
}

4
投票

您的第二个 xpath 以

//
开头。这是
/descendant-or-self::node()
的缩写,您可以看到它以
/
开头,这意味着它会从文档的根目录搜索,无论您在什么上下文中使用它。

您可能想要以下之一:

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

找到作为

name
直接子节点
row
节点,或者

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

在第二个 xpath 中的

name
row
the
.` 下找到
. Note the
节点*任意位置,这会导致 xpath 从上下文节点开始。


3
投票

使用相对路径,例如

string rowName = row.SelectSingleNode("name").InnerText;


2
投票

问题出在您的第二个 XPath 查询中:

//row

它具有全局作用域,因此无论您从哪里调用它,它都会选择 all

row
元素。

如果将表达式替换为:

,应该会起作用
.//row

2
投票

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

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

0
投票

使用以下内容

        doc.LoadXml(xml);

            foreach(XmlNode row in doc.SelectNodes("/rows/row"))
            {
                string rowName = row.SelectSingleNode("//name").InnerText.ToString();
            }

0
投票

下面以 XML 为例,使用 XPath 获取文档数据

<?xml version="1.0" encoding="UTF-8" ?>    <!DOCTYPE svg (View Source for full doctype...)>   <!-- Created with AIM.   -->   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1668.75 1074.75" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" zoomAndPan="magnify" version="1.0" contentScriptType="text/ecmascript" contentStyleType="text/css">   can't read ": no such element in array    <g id="#1" class="track" />  <g id="#5" class="dedication">  <metadata>   <meta name="color">Red</meta>    </metadata>   <text fill="#181818">AQWSD</text>    </g>  <g id="#6" class="wordasword">  <metadata>   <meta name="epigraph">Output 1</meta>    <meta name="color">Red</meta>    <meta name="refentry">qandadiv</meta>    </metadata>   <paramdef fill="none" />    <text fill="#181818">0.35</text>    </g>  <g id="#7" class="wordasword">  <metadata>   <meta name="epigraph">Output 2</meta>    <meta name="color">Red</meta>    <meta name="refentry">calloutlist</meta>    <meta name="screen">common></meta>   </metadata>   <path fill="none" />    <text fill="#181818">lineannotation</text>    <text fill="#181818">WHO</text>    <paramdef fill="#232323" />    </g>  <g id="#" class="wordasword">  <metadata>   <meta name="epigraph">Output 3</meta>    <meta name="color">Red</meta>    <meta name="refentry">calloutlist</meta>    <meta name="screen">common></meta>    </metadata>   <path fill="none" />    <text fill="#181818">lineannotation</text>    <text fill="#181818">WHO</text>    <paramdef fill="#232323" />    </g>   </svg>

我已经检查并构建了下面运行正常的代码。下面是上述 XML 文档的运行时值 xmlContent

var xmlContent =“ 无法读取“:数组中没有这样的元素 红色 AQWSD 输出1 红色 qandadiv 0.35 输出2 红色 标注列表 常见> 行注释 世界卫生组织 输出3 红色 标注列表 常见> 行注释 世界卫生组织 ”;

XmlDocument xml = new XmlDocument();
                xml.LoadXml(xmlContent);

                //Select all g Nodes of class wordasword that have color red in metadata>meta 
                var gNodesOnClassOfColorRed = xml.SelectNodes("//*[local-name()='g'][@class='wordasword'][*[local-name()='metadata'][*[local-name()='meta'][@name='color'] = 'Red']]").Cast<XmlNode>();

                foreach (XmlNode gNode in gNodesOnClassOfColorRed)
                {
                    var metadata = gNode.SelectSingleNode("*[local-name()='metadata']").Cast<XmlNode>();    //Fetch metadata of g tag

                    //Fetch epigraph value from meta tag from metadata
                    var epigraph = metadata.Cast<XmlNode>()
                                    .Where(z => z.Attributes.Count != 0 && z.Attributes.GetNamedItem("name") != null && z.Attributes.GetNamedItem("name").Value.Trim().ToLower() == "epigraph")
                                    .Select(p => p.InnerText).FirstOrDefault();
                    Console.WriteLine(epigraph);
                }

铭文值的输出将打印为

输出1、输出2、输出3

© www.soinside.com 2019 - 2024. All rights reserved.