Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

excel - Xpath syntax to select nodes with multiple attributes in the path

My xml tree contains this in the structure

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

I'm trying to refer to anywhere in the tree where location order ="2" (there could be 1000s of them) to manipulate all data2 texts. I cannot get vba to recognize it with an xpath string assignment.

I've tried many things but the thing that makes the makes the most sense to me is

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

It does however recognize the xPath assignment to foo if I remove.

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

Am I doing something wrong in the xpath syntax? Or is there more to assigning a path to a node containing several attributes to be selected in the tree structure?

Maybe I'm trying to use the wrong methods to access the variable?

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

Gives me a 0 but there are two instances of those specific nodes in my xml

Edit: Still giving me zero after doing some things with yours. Here's an example xml so you can see namespace. I can still get it to print a length if I leave out the "/location[@order='2']". Also to clarify, I only am interested in the path that is , there could be many other foo nodes with the child . These I do not care about for now.

    <?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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EDITED

Using your updated XML, this code gives me "data2" and "data2" as output:

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

Similar Q previously: How to ignore a XML namespace


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...