【问题标题】:Xpath syntax to select nodes with multiple attributes in the path用于选择路径中具有多个属性的节点的 Xpath 语法
【发布时间】:2017-08-01 02:23:24
【问题描述】:

我的 xml 树在结构中包含这个

<foo name="bar">
    <location order="1">data1</location>
    <location order="2">data2</location>
</foo>

我试图引用树中位置顺序 =“2”(可能有 1000 个)的任何位置来操作所有 data2 文本。我无法通过 xpath 字符串分配让 vba 识别它。

我尝试了很多东西,但对我来说最有意义的是

xPath = "//prefix:foo[@name='bar']/location[@order='2']" 

但是,如果我删除它,它确实会识别到 foo 的 xPath 分配。

"/location[@order='2']"

我在 xpath 语法中做错了吗?或者是否有更多的方法来为包含要在树结构中选择的多个属性的节点分配路径?

也许我试图使用错误的方法来访问变量?

Dim list as IXMLDOMNodeList
Set list = xDoc.SelectNodes(xPath)
Debug.Print list.length

给我一​​个 0,但我的 xml 中有两个特定节点的实例

编辑: 和你做了一些事情后仍然给我零。这是一个示例 xml,因此您可以查看命名空间。如果我省略“/location[@order='2']”,我仍然可以让它打印一个长度。另外澄清一下,我只对路径感兴趣,即可能有许多其他 foo 节点与 child 。这些我暂时不关心。

    <?xml version="1.0" encoding="utf-8"?>
    <IPSGDatas xsi:schemaLocation="uri:mybikes:wheels MYBIKES%20WHEELS%202012.xsd" 
      xmlns="uri:mybikes:wheels" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <header>
            <language_id>120</language_id>
        </header>
        <datas>
            <good>
                <signature/>
                <bike>
                    <foos>
                        <marker>
                            <location order="1">data1</location>
                            <location order="2">data2</location>
                        </marker>
                        <foo name="bar">
                            <location order="1">data1</location>
                            <location order="2">data2</location>
                        </foo>
                    </foos>
                    <profile_id>MyName1</profile_id>
                </bike>
                <action_id>New</action_id>
                <index_id>1</index_id>
                <agency/>
                <agency_reference/>
                <accreditation_id>U</accreditation_id>
            </good>
            <good>
                <signature/>
                <bike>
                    <foos>
                        <marker>
                            <location order="1">data1</location>
                            <location order="2">data2</location>
                        </marker>
                        <foo name="bar">
                            <location order="1">data1</location>
                            <location order="2">data2</location>
                        </foo>
                    </foos>
                    <profile_id>MyName2</profile_id>
                </bike>
                <action_id>New</action_id>
                <index_id>1</index_id>
                <agency/>
                <agency_reference/>
                <accreditation_id>U</accreditation_id>
            </good>
        </datas>
    </IPSGDatas>

【问题讨论】:

  • "foo[@name='bar']/location[@order='2']" 为我工作-但您似乎没有在示例 XML 中包含一些命名空间,因此很难确定。你能让它更能代表你的实际用例吗?
  • 嗯。从我的手机打字并在没有访问权限的情况下在笔记本电脑上处理文件。给我一点,直到我这样做,我会看看我能做什么。目前,我可以告诉你命名空间在没有 location order="2" 节点的情况下工作得很好。
  • :/ 可能我用错了方法。
  • 我正在尝试使用访问变量
  • 对不起,我会编辑帖子...

标签: excel vba


【解决方案1】:

已编辑

使用您更新的 XML,此代码将“data2”和“data2”作为输出:

Sub Tester3()

    Dim xmlDoc As New MSXML2.DOMDocument30
    Dim objNodes As IXMLDOMNodeList, o As Object

    xmlDoc.async = False
    xmlDoc.LoadXML Range("C1").Value
    xmlDoc.setProperty "SelectionLanguage", "XPath"

    '### this takes care of the namespace ###
    xmlDoc.setProperty "SelectionNamespaces", _
                     "xmlns:xx='uri:mybikes:wheels'"

    If xmlDoc.parseError.errorCode <> 0 Then

        MsgBox "Error!" & vbCrLf & _
        "  Line: " & xmlDoc.parseError.Line & vbCrLf & _
        "  Text:" & xmlDoc.parseError.srcText & vbCrLf & _
        "  Reason: " & xmlDoc.parseError.reason

    Else
        '### note: adding the namespace alias prefix defined above ###
        Set objNodes = xmlDoc.SelectNodes("//xx:foo[@name='bar']/xx:location[@order='2']")

        If objNodes.Length = 0 Then
            Debug.Print "not found"
        Else
            For Each o In objNodes
                Debug.Print o.nodeTypedValue
            Next o
        End If 'have line items

    End If 'parsed OK
End Sub

之前的类似Q:How to ignore a XML namespace

【讨论】:

  • 感谢蒂姆的帮助!我没有将他的命名空间前缀设置为“xx”,尽管我确实注意到在 xPath 字符串中的第二个属性之前包含前缀......所以我做了同样的事情,瞧!这正是我一直在寻找的,而且效果很好!再次非常感谢!
  • 我必须阅读更多关于命名空间和 xpath 的内容。我以为我做得很好……不是这样的。
猜你喜欢
  • 2015-04-10
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 2012-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多