首页 > 解决方案 > 如何在 XPath .net 应用程序中按索引选择元素

问题描述

我从 Web 服务收到以下 xml

<GRID xmlns="http://schemas.datastream.net/MP_functions/MP0118_GetGridHeaderData_001_Result">
  <DATA>
    <R>
      <D>2645</D>
      <D>HJIT.HRE@RGW.COM</D>
      <D>2019-09-27 10:17:36.0</D>
      <D>114041</D>
      <D>Awaiting Planning</D>
      <D>Work Planned</D>
    </R>
    <R>
      <D>2649</D>
      <D>HJIT.HRE@RGW.COM</D>
      <D>2019-09-27 10:33:24.0</D>
      <D>114043</D>
      <D>Awaiting Release</D>
      <D>Awaiting Planning</D>
    </R>
    <R>
      <D>2652</D>
      <D>HJIT.HRE@RGW.COM</D>
      <D>2019-09-27 10:36:53.0</D>
      <D>114041</D>
      <D>Awaiting Planning</D>
      <D>Work Planned</D>
    </R>
  </DATA>
</GRID>

我编写了以下 .NET 代码来提取 R 节点

HttpWebResponse resp = (HttpWebResponse)Req.GetResponse();

XPathDocument xpResDoc = new XPathDocument(resp.GetResponseStream());
XPathNavigator xpNav = xpResDoc.CreateNavigator();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xpNav.NameTable);
nsmgr.AddNamespace("g2", "http://schemas.datastream.net/MP_functions/MP0118_GetGridHeaderData_001_Result");

XPathNodeIterator xpNIter = xpNav.Select("//g2:R", nsmgr); // I can successfully get the three R elements 

foreach (XPathNavigator nav in xpNIter)
{

    /*
        Now I want to iterate through each R element and use XPATH to select each of the six D nodes by its index position.
        The order of the D nodes are a known dataset and I want to build a comma separated string by concatenating the value of each D node,
        which will later be appended to a CSV file along with a pre-defined header row.
    */

    /* I attempted the following XPATH */

    // XPathNodeIterator xpDi = nav.Select("(//D)[1]"); -- This does not work and yields a null result
}

现在我想遍历每个 R 元素并使用 XPATH 通过索引位置选择六个 D 节点中的每一个。D 节点的顺序是一个已知的数据集,我想通过连接每个 D 节点的值来构建一个逗号分隔的字符串,该值稍后将与预定义的标题行一起附加到 CSV 文件中。

我不想使用像 LINQ to XML 这样的东西,因为这是只读数据提取程序的一部分,它需要尽可能精简和高性能。

使用 XPathNavigator 通过 XPATH 索引获取 D 元素的正确方法是什么?

标签: c#.netxmlxpath

解决方案


我在正确的道路上,只需要使用允许指定命名空间的正确方法,如下所示:

HttpWebResponse resp = (HttpWebResponse)Req.GetResponse();

XPathDocument xpResDoc = new XPathDocument(resp.GetResponseStream());
XPathNavigator xpNav = xpResDoc.CreateNavigator();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xpNav.NameTable);
nsmgr.AddNamespace("g2", "http://schemas.datastream.net/MP_functions/MP0118_GetGridHeaderData_001_Result");

XPathNodeIterator xpNIter = xpNav.Select("//g2:R", nsmgr);

foreach (XPathNavigator nav in xpNIter)
{

    string r = 
        $"{nav.SelectSingleNode("./g2:D[1]", nsmgr).Value}," +
        $"{nav.SelectSingleNode("./g2:D[2]", nsmgr).Value}," +
        $"{nav.SelectSingleNode("./g2:D[3]", nsmgr).Value}," +
        $"{nav.SelectSingleNode("./g2:D[4]", nsmgr).Value}," +
        $"{nav.SelectSingleNode("./g2:D[5]", nsmgr).Value}," +
        $"{nav.SelectSingleNode("./g2:D[6]", nsmgr).Value}";

    Console.WriteLine(r);
}

// Start writing to a file stream;

推荐阅读