【问题标题】:Access element having a specific attribute using XPath in VB.net在 VB.net 中使用 XPath 访问具有特定属性的元素
【发布时间】:2016-07-23 08:51:13
【问题描述】:

由于使用 XPath 获取具有特定属性的元素花费了太多时间,我一直在苦苦挣扎。

下面是我要从中获取元素的wsdl:

    <?xml version="1.0" encoding="UTF-8"?>

<!-- Copyright Zuora, Inc. 2007 - 2010 All Rights Reserved. -->

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:zns="http://api.zuora.com/" 
    xmlns:ons="http://object.api.zuora.com/"
    xmlns:fns="http://fault.api.zuora.com/"
    targetNamespace="http://api.zuora.com/">
    <types>


<schema attributeFormDefault="qualified" elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://object.api.zuora.com/">
                <import namespace="http://api.zuora.com/" />
                <complexType name="zObject">
                <sequence>
                    <element minOccurs="0" maxOccurs="unbounded" name="fieldsToNull" nillable="true" type="string" />
                    <element minOccurs="0" maxOccurs="1" name="Id" nillable="true" type="zns:ID" />
                </sequence>
            </complexType>


            <complexType name="AccountingCode" >
                <complexContent>
                    <extension base="ons:zObject">
                        <sequence>
                            <element minOccurs="0" name="Category" nillable="true" type="string" />
                            <element minOccurs="0" name="CreatedById" nillable="true" type="zns:ID" />
                            <element minOccurs="0" name="CreatedDate" nillable="true" type="dateTime" />
                            <element minOccurs="0" name="GLAccountName" nillable="true" type="string"   />
                            <element minOccurs="0" name="GLAccountNumber" nillable="true" type="string"   />
                            <element minOccurs="0" name="Name" nillable="false" type="string" />
                            <element minOccurs="0" name="Notes" nillable="true" type="string" />
                            <element minOccurs="0" name="Status" nillable="true" type="string" />
                            <element minOccurs="0" name="Type" nillable="false" type="string" />
                            <element minOccurs="0" name="UpdatedById" nillable="true" type="zns:ID" />
                            <element minOccurs="0" name="UpdatedDate" nillable="true" type="dateTime" />
                        </sequence>
                    </extension>
                </complexContent>
            </complexType>

            <complexType name="AccountingPeriod" >
                <complexContent>
                    <extension base="ons:zObject">
                        <sequence>
                            <element minOccurs="0" name="CreatedById" nillable="true" type="zns:ID" />
                            <element minOccurs="0" name="CreatedDate" nillable="true" type="dateTime" />
                            <element minOccurs="0" name="EndDate" nillable="true" type="date" />
                            <element minOccurs="0" name="FiscalYear" nillable="true" type="int" />
                            <element minOccurs="0" name="Name" nillable="true" type="string" />
                            <element minOccurs="0" name="Notes" nillable="true" type="string" />
                            <element minOccurs="0" name="StartDate" nillable="true" type="date" />
                            <element minOccurs="0" name="Status" nillable="true" type="string" />
                            <element minOccurs="0" name="UpdatedById" nillable="true" type="zns:ID" />
                            <element minOccurs="0" name="UpdatedDate" nillable="true" type="dateTime" />
                        </sequence>
                    </extension>
                </complexContent>
            </complexType>
        </schema>
    </types>
</definitions>

在这个 wsdl 中定义了多个命名空间:

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" 
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:zns="http://api.zuora.com/" 
xmlns:ons="http://object.api.zuora.com/"
xmlns:fns="http://fault.api.zuora.com/"
targetNamespace="http://api.zuora.com/">

下面是我非常简单的一段代码。我很确定我的问题出在命名空间上,但尽管搜索了很多尝试的解决方案,但我无法解决它:

Public Sub constituteLocalDictionnary()

    Dim pathWsdlFile As String
    pathWsdlFile = My.Settings.ZuoraUrlWSDL

    Dim doc As New XmlDocument()
    doc.Load(pathWsdlFile)



    Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
    nsmgr.AddNamespace("ns", "http://schemas.xmlsoap.org/wsdl/")
    nsmgr.AddNamespace("ons", "http://object.api.zuora.com/")

    Dim myXmlPath As String
    myXmlPath = "//ns:complexType[@name='" & ZuoraWsdlObjectsList(1) & "']"

    Dim root As XmlElement = doc.DocumentElement
    Dim node As XmlNode = root.SelectSingleNode(myXmlPath, nsmgr)

End Sub

【问题讨论】:

  • 我所有的礼貌公式都在复制和粘贴后用于验证这篇文章。有一些大家好...非常感谢您的帮助...类似的事情:)对于原始帖子的粗糙方面感到抱歉。

标签: xml vb.net xpath namespaces


【解决方案1】:

您使用了错误的命名空间来引用 complexType 元素。 complexType 实际上从其父元素 schema 而不是根元素继承 默认命名空间,因为父元素更近,因此从外部元素上下文覆盖默认命名空间:

<schema attributeFormDefault="qualified" elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://object.api.zuora.com/">
    <import namespace="http://api.zuora.com/" />
    <complexType name="zObject">
        ....
    </complexType>
    ....
</schema>       

试试这个方法:

....

Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
nsmgr.AddNamespace("ns2", "http://www.w3.org/2001/XMLSchema")

Dim myXmlPath As String
myXmlPath = "//ns2:complexType[@name='" & ZuoraWsdlObjectsList(1) & "']"

【讨论】:

  • 非常感谢!这解决了我的问题。而且我现在更好地理解了如何正确处理名称空间。
  • @stef 欢迎您。不要忘记接受您认为更合适的答案 (read more)
【解决方案2】:

代码使用 Xml Linq 非常简单

Imports System.Xml
Imports System.Xml.Linq

Module Module1
    Const FILENAME As String = "c:\temp\test.xml"
    Sub Main()
        Dim doc As XDocument = XDocument.Load(FILENAME)
        Dim results = doc.Descendants().Where(Function(x) x.Name.LocalName = "complexType").Select(Function(y) New With { _
                .name = y.Attribute("name"),
                .elements = y.Descendants(y.Name.Namespace + "element").Select(Function(z) New With { _
                     .minOccurs = CType(z.Attribute("minOccurs"), Integer), _
                     .name = CType(z.Attribute("name"), String), _
                     .nillable = CType(z.Attribute("nillable"), Boolean), _
                     .type = CType(z.Attribute("type"), String) _
                 }).ToList()
        }).ToList()
    End Sub

End Module

【讨论】:

  • 谢谢,但我在 ce 上使用了 XPath 解决方案,我的命名空间已经解决。与使用 Linq ("//ns:complexType[@name='" & ZuoraWsdlObjectsList(1) & "']/ns:complexContent/ns:extension/ns: sequence/ns:element") 和一个 selectNodes 而不是 SelectSingleNode
  • 我的解决方案是通用的,适用于任何命名空间。我从 xml 数据中提取名称空间,而不是对名称空间进行硬编码。我的解决方案还获得了一个 complexType 数组,而您的解决方案只获得了一个 complexType。
  • 确实你是对的。我没有精确这一点,但在我的解决方案中,我需要直接转到名称等于某物的特定 complecType 元素(存储在多维数组 ZuoraWsdlObjectsList 中),然后我从另一个数组中获取所有元素,这正是我需要的。但可以肯定的是,我会看看你的解决方案,也许我会改变主意。 :) 非常感谢。
  • 您可以添加 WHERE 以获取特定名称。
猜你喜欢
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 2011-05-30
  • 2019-01-22
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
相关资源
最近更新 更多