【问题标题】:VBA Xpath Wildcard For Letters字母的 VBA Xpath 通配符
【发布时间】:2015-06-22 00:01:51
【问题描述】:
<?xml version="1.0"?>
<catalog>
<book id="Adventure">
   <author>Gambardella, Matthew</author>
   <title>XML Developer's Guide</title>
   <price>44.95</price>
   <misc>
        <Publisher id="5691">
            <PublisherLocation>Los Angeles</PublisherLocation>
        </Publisher>
        <PublishedAuthor fName="Gambardella">
            <StoreLocation>Store B</StoreLocation>
        </PublishedAuthor>
    </misc>
</book>
<book id="Adventure">
   <author>Ralls, Kim</author>
   <title>Midnight Rain</title>
   <price>5.95</price>
   <misc>
        <Publisher id="4787">
            <PublisherLocation>New York</PublisherLocation>
        </Publisher>
        <PublishedAuthor Name="Ralls">
            <StoreLocation>Store B</StoreLocation>
        </PublishedAuthor>
    </misc>
</book>
</catalog>

PublishedAuthor 的路径对于两本书都是相同的,除了一个字符。是否可以为此字符设置通配符,以便它接受任一 XPath?

&lt;catalog/book/misc/PublishedAuthor[@fName=]/

产生与以下内容完全相同的结果:

&lt;catalog/book/misc/PublishedAuthor[@Name=]/

【问题讨论】:

    标签: vba dom xpath xml-parsing


    【解决方案1】:

    如果属性名称可以是NamefName,那么您可以使用:

    Sub Tester()
        Dim doc As New MSXML2.DOMDocument
        Dim n
    
        doc.LoadXML Range("a1").Value
    
        Set n = doc.SelectNodes("/catalog/book/misc/PublishedAuthor[@Name='Ralls']|" & _
                                "/catalog/book/misc/PublishedAuthor[@fName='Ralls']")
    
        Debug.Print n.Length '>> 2
    
    End Sub
    

    没有可用于属性名称的通配符。

    【讨论】:

    • 谢谢!但是如果它是属性之后的节点呢?从上面的示例中,说出类似 &lt;catalog/book/misc/PublishedAuthor[@fName=]/StoreLocation/&lt;catalog/book/misc/PublishedAuthor[@fName=]/StoreLocations/ 之类的内容,其中我们有 StoreLocation 和 StoreLocations
    • 抱歉,我的意思更像是 &lt;catalog/book/misc/PublishedAuthor/area/StoreLocation/&lt;catalog/book/misc/PublishedAuthors/area/StoreLocation/,其中没有直接的百搭属性,但中间有一个略有不同的节点(在这种情况下,PublishedAuthorsPublishedAuthor)
    【解决方案2】:

    XPath 中没有专门用于字母的通配符。您可能已经意识到,通配符适用于整个名称(元素名称或属性名称)。要在 xpath 中部分匹配,您可能需要考虑 starts-with()substring() 函数。

    对于这种特定情况,可能的替代方法是使用 or 运算符,这将使您免于编写相同的路径两次,例如使用联合 (|) 运算符时:

    /catalog/book/misc/PublishedAuthor[@fName or @Name]
    

    关于您的评论,您可以使用starts-with() 检查节点的name(),如下所示:

    /catalog/book/misc/*[starts-with(name(), 'PublishedAuthor')]/area/StoreLocation
    

    【讨论】:

    • 有趣。我也可以在技术上做到&lt;catalog/book/misc/PublishedAuthor/area/[contains[name(),'StoreLocation']/ 甚至&lt;catalog/book/misc/PublishedAuthor/area/[ends-with(name(),'Location']/ 对吗?
    • contains(name(),'StoreLocation') 也应该可以工作,但ends-with() 可能不是因为它是 xpath 2.0 函数(AFAIK,大多数 xpath 引擎/库仅实现 xpath 1.0)。供参考:xpath 1.0 spec
    • 对不起另一个问题,但我的上下文有问题:Set loc = pn.SelectSingleNode("misc/PublishedAuthor/contains(name(),'StoreLocation')") VBA 在这种情况下似乎不喜欢括号,当我删除括号时,VBA 似乎不喜欢比如包含这个词。知道为什么吗? :( 另外,我注意到网上很多其他人在声明他们的 XPath 时不使用“引号”,这只是为了演示目的吗?
    猜你喜欢
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 2019-04-19
    • 2016-06-02
    • 1970-01-01
    相关资源
    最近更新 更多