【问题标题】:Better way to write this XPath expression编写此 XPath 表达式的更好方法
【发布时间】:2014-01-06 03:12:34
【问题描述】:

有没有更简单的方法来编写这个 XPath 表达式,特别是最后一行。我正在从 tshark 搜索 XML 转储,以查找具有某些属性的某个数据包。这是我的 XPath 表达式

count(//packet[
  proto/@name="dhcpv6"
  and .//field/@showname="Message type: Solicit (1)"
  and .//field/@show="Link-layer address: 30:00:01:dc:d9:82"
  and .//field[@show="Interface-Id"]/field[@show="option type: 18"]/../field[@show="Interface-ID: AVC-0123456789"]])

这是获取数据包的计数

1) Contain a child of <proto name="dhcpv6">
2) Contain a descendant of <field showname="Message type: Solicit (1)/">
3) Contain a descendant of <field show="Link-layer address: 30:00:01:dc:d9:82"/>
4) Contain a descendant of
   <field show="Interface-Id">
     <field show="option type: 18"/>
     <field show="Interface-ID: AVC-0123456789"/>
   </field>

我不喜欢的一点是它找到“选项类型:18”,然后返回父级并查找“接口 ID:AVC-0123456789”。有没有办法用'and'语句来写这个?它有效,但有点令人困惑和难以理解的 IMO。

这是 XML 的简化版本。请注意,字段标签可能在多个级别内,这就是我使用 .// 的原因。

<?xml version="1.0"?>
<packet>
  <proto name="dhcpv6">
    <field showname="Message type: Solicit (1)"/>
    <field show="Link-layer address: 30:00:01:dc:d9:82"/>
    <field show="Interface-Id">
      <field show="option type: 18"/>
      <field show="Interface-ID: AVC-0123456789"/>
    </field>
  </proto>
</packet>

顺便说一句,我坚持使用 XPath 1.0,因为这是我目前使用的工具所支持的。

【问题讨论】:

    标签: xml xpath wireshark


    【解决方案1】:

    以下似乎可行,对我来说更有意义:

    count(//packet[
        proto/@name="dhcpv6"
        and .//field/@showname="Message type: Solicit (1)"
        and .//field/@show="Link-layer address: 30:00:01:dc:d9:82"
        and .//field[@show="Interface-Id"
            and field[@show="option type: 18"]
            and field[@show="Interface-ID: AVC-0123456789"]
        ]
    ])
    

    基本上第三条标准说:

    • 字段后代
      • “Inferface-Id”的“show”属性
      • 具有“选项类型:18”的“显示”属性的子字段
      • 具有“接口 ID:AVC-0123456789”的“显示”属性的子字段

    你也可以这样写:

    count(//packet[
        proto/@name="dhcpv6"
        and .//field/@showname="Message type: Solicit (1)"
        and .//field/@show="Link-layer address: 30:00:01:dc:d9:82"
        and .//field
            [@show="Interface-Id"]
            [field[@show="option type: 18"]]
            [field[@show="Interface-ID: AVC-0123456789"]]
    ])
    

    这意味着第三个.//field必须满足所有三个缩进条件。

    【讨论】:

    • 谢谢,这正是我想要的。我还在学习 XPath,并没有意识到你可以像这样嵌套谓词。我开始越来越喜欢它了。 :-)
    【解决方案2】:

    这对你有用吗?

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"/>  
    <xsl:variable name="count" select="count(//packet/proto[@name='dhcpv6' and  /.//field[@showname='Message type: Solicit (1)'] and .//field[@show='Link-layer address: 30:00:01:dc:d9:82']
    and .//field[@show='Interface-Id'] and ./field[@show='option type: 18'] and ./field[@show='Interface-ID: AVC-0123456789']])"/>
    
    <xsl:template match="/">
    <div>
        Count is: <xsl:value-of select="$count"/>
    </div>
    
    
    </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • 嗨,Alex,你能告诉我 /.// 是做什么的吗?我理解 .// 是后代的捷径::
    • 感谢您的回复,但不幸的是它看起来没有。对于最后 3 个字段,我需要匹配该确切结构,即带有 show=Interface-Id 的字段,并且在该字段下指定了其他 2 个值。有了你的,我可以在任何布局中将它们指定为 3 个字段,它仍然匹配。
    • 如果你尝试这个:
    • 嗨,Alex,这是同一个问题,最后 2 个字段必须是倒数第三个字段的子字段。该查询将匹配 proto 下任何位置的这 3 个字段。即使 'option type: 18' 是 'Interface-Id' 的父级,它仍然会匹配,这不是我想要的。
    • 如果他们总是直接的孩子,那么对于这两个替换 .// 只是 /
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 2013-01-14
    • 2017-08-19
    相关资源
    最近更新 更多