【问题标题】:Reading child nodes with multiple namespaces读取具有多个命名空间的子节点
【发布时间】:2018-06-03 00:16:07
【问题描述】:

有很多关于命名空间和读取 XML 节点的帖子,但我一直无法找到特定查询的答案。我相信我的方法是正确的,但我显然遗漏了一些阻止它工作的东西。

概述 - 我正在进行 Web 服务调用,它返回我需要清理并动态创建和填充数据表的 XML。为了清理,我试图从包含多个命名空间的返回 XML 中读取我需要的节点。

我可以从文档中获取数据,但不能达到我想要的级别。我希望 XMLContent 节点列表包含“容器”级别的数据。

代码中的 cmets 显示了为我提供数据但未达到所需级别的行,以及我希望返回下一个级别但它不返回任何内容的行。我很高兴得到我需要的东西,我需要降级,但这是节点列表返回 null 的地方。

我不能不先操作就将 XML 加载到数据集或数据表中。

示例 XML

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="namespaceone" xmlns:xsi="namespacetwo" xmlns:xsd="namespacethree">
    <soap:Body>
        <Response xmlns="http://namespacefour">
            <Result>
                <Data xmlns="http://namespacefive" xmlns:t="http://namespacesix">
                    <Container>
                        <Properties>
                            <Property1>a</Property1>
                            <Property2>b</Property2>
                        </Properties>
                    </Container>
                    <Container>
                        <Properties>
                            <Property1>c</Property1>
                            <Property2>d</Property2>
                        </Properties>
                    </Container>
                </Data>
            </Result>
        </Response>
    </soap:Body>
</soap:Envelope>
        Dim XMLdoc As XmlDocument = New XmlDocument()
        XMLdoc.LoadXml(strXML)

        Dim XMLContent As XmlNodeList

        Dim nsMgr As New XmlNamespaceManager(XMLdoc.NameTable())
        ns.AddNamespace("dflt", XMLdoc.DocumentElement.NamespaceURI)
        ns.AddNamespace("ns1", XMLdoc.DocumentElement.GetNamespaceOfPrefix("soap"))
        ns.AddNamespace("ns2", "http://namespacetwo")
        ns.AddNamespace("ns3", "http://namespacethree")
        ns.AddNamespace("ns4", "http://namespacefour")
        ns.AddNamespace("ns5", "http://namespacefive")
        ns.AddNamespace("ns6", "http://namespacesix")

        'This returns content but not at the level I want
        XMLContent = XMLdoc.SelectNodes("/ns1:Envelope/ns1:Body/ns4:Response/ns4:Result", nsMgr)

        'This does not return anything
        XMLContent = XMLdoc.SelectNodes("/ns1:Envelope/ns1:Body/ns4:Response/ns4:Result/ns5:Data", nsMgr)

        If Not XMLContent Is Nothing Then
            For Each node As XmlNode In XMLContent
                'Create and populate table here
            Next node
        End If

感谢您的帮助。

【问题讨论】:

  • 能否请您发布一个您正在运行 XPATH 的示例文档?还有一个一般性建议 - 尝试让您的查询更通用一点,这样它就不会关心 NS,例如//Response/Result/Data
  • 同意@t1gor 对示例文档的要求。它应该作为文本添加,不是作为图像
  • 公平人士 - 将图像更改为 XML 的代码示例。将调查更通用的查询。
  • 我尝试测试您的代码,第二个 SelectNodes() 调用成功选择了 &lt;Data&gt; 节点。见dotnetfiddle.net/zbdTZ6。但是您的代码存在一个问题——您定义了一个变量Dim nsMgr As ...,但随后将命名空间添加到名为ns 的不同名称中。因此,您的代码不能独立编译,所以我在小提琴中修复了它。但也许在您的“真实”代码中ns 实际已定义,并且您将命名空间添加到错误的XmlNamespaceManager
  • 感谢您回复 dbc。 ns nsMgr 只是我的重构错误 - 代码在测试平台中,所以我在发布之前重命名了一些位并错过了它。我不明白。我看到它在小提琴中工作,这正是我所期望的,因为更高级别的节点匹配良好,但我的测试台中的代码在低于该级别的任何内容上都不会匹配。我将再次关注命名空间。谢谢。

标签: xml vb.net xpath namespaces


【解决方案1】:

不是最优雅的方式,但会起作用:

//*[local-name(.) = 'Response']/*[local-name(.) = 'Result']/*[local-name(.) = 'Data']

也是独立于 NS 的。 Testing link.

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    感谢大家的建议,但我已经破解了。事实证明,XML 是从数据节点及其下方编码的,尽管外部节点未编码。我应该已经发现了这一点,但没想到编码和非编码的混合。无论如何,如果我在 Web 服务输出上运行 HttpUtility.HtmlDecode,那么我最初发布的代码可以正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 2018-08-08
      • 1970-01-01
      • 2018-05-30
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多