【问题标题】:Need a complex Xpath using sibling children, ancestors需要使用兄弟孩子、祖先的复杂 Xpath
【发布时间】:2023-03-13 16:45:01
【问题描述】:

我需要根据从父母/祖父母的兄弟姐妹的孩子中提取的其他值来查找属性值。我认为这需要两种不同的表达方式。

因此,给定以下 XML(源自可能长达数千行的日志文件):

<p:log xmlns:p="urn:NamespaceInfo">
 <p:entries>
   <p:entry timestamp="2012-12-31T09:39:25">
     <p:attributes>
       <p:attrib name="Position" value="1B2" />
       <p:attrib name="Something" value="Something_else" />
     </p:attributes>
     <p:msg>
     </p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T09:39:25">
     <p:attributes>
       <p:attrib name="Form" value="FormA" />
     </p:attributes>
     <p:msg>
     </p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T09:39:25">
     <p:msg>Successful....</p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T12:12:12">
     <p:attributes>
       <p:attrib name="Position" value="1B3" />
       <p:attrib name="Something" value="Something_else" />
     </p:attributes>
     <p:msg>
     </p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T09:39:25">
     <p:attributes>
       <p:attrib name="Form" value="FormB" />
     </p:attributes>
     <p:msg>
     </p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T09:39:25">
     <p:msg>Processing....</p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T09:39:25">
     <p:msg>Error1</p:msg>
   </p:entry>
   <p:entry timestamp="2012-12-31T09:39:25">
    <p:msg>Error1</p:msg>
   </p:entry>
 </p:entries>
     ...
</p:log>
  • &lt;p:attributes&gt;父标签可以有多个&lt;p:attrib&gt;子标签)
  • &lt;p:event&gt;标签只能有一个&lt;p:msg&gt;标签)

首先,我需要获取具有Position 的对应name 属性的value 属性的值,但前提是祖父母的兄弟姐妹p:entry 有一个孩子p:msg 与文本的Error1。此外,它需要留在该部分内。例如,我不希望第一次出现 Position'/'Value 对,因为新的 Position/Value 对出现在 Error1 之前,即使从技术上讲,p:msgError1 是兄弟姐妹祖父母。

接下来,我需要我刚刚抓取的Position/Value 的孩子的父母的时间戳属性值。所以,找到位置,然后找到祖父p:entry标签的时间戳属性值。

所以对于这个例子,我应该只能检索以下值:

1B3

2012-12-31T12:12:12(给出的日期/时间戳是任意值。这个不同,所以你知道我引用的是哪一个)。

我知道有点令人困惑。我还需要确保只获取一个实例,因为我使用 XQuery 从数据库中获取数据,并且每个表达式都必须生成一个奇异值。

我可以通过Error1 获得与p:msg 关联的第一个时间戳://p:entry[descendant::p:msg='Error1.'][1]/@timestamp

但似乎无法回到树上以获取其他值。

我可以获得具有 p:attrib 孙子的 p:events 的所有时间戳://p:entry[descendant::p:attrib[@name=''Position'']]/@timestamp)[1]

但我似乎无法将其限制为仅在其后有“Error1”的那个。我不能根据职位进行选择。我必须首先基于内容。

奖金问题

如何在日志文件的下一个实例中再次执行此操作? (不仅仅是第二条Error1 消息,下一次在日志文件中显示Error1 消息以用于下一个“父/兄弟”匹配)。一旦我得到上述问题的答案,这可能是显而易见的。

【问题讨论】:

    标签: xpath xquery-sql tree-traversal siblings


    【解决方案1】:

    更新

    好的,我想我明白了。这是第一个的答案:

    //p:msg[text()="Error1"]/../preceding-sibling::p:entry[./*/p:attrib[@name="Position"]][1]/*/p:attrib[@name="Position"]/@value
    

    这是来自p:msg 标签的back,这使得选择满足条件的前一个父p:entry 标签的第一个(即那里的[1])变得更容易他们有一个孙子p:attrib,名字是Position

    获取时间戳稍微简单一点:

    //p:msg[text()="Error1"]/../preceding-sibling::p:entry[./*/p:attrib[@name="Position"]][1]/@timestamp
    

    试试看,看看你的想法。

    原始答案

    通常我不会发布半成品的答案,但我猜你不会得到任何其他东西,因为这个问题太复杂了,所以这是你在第一段中描述的 xpath:

    //p:entry[following-sibling::p:entry/p:msg/text()="Error1"]/*/p:attrib[@name="Position"]/@value
    

    这会得到

    具有对应名称属性Position的value属性的值,但前提是祖父母的兄弟p:entry有一个带有Error1文本的子p:msg。

    但是,当您说“它需要保留在该部分中”时,我不知道您的意思。你能澄清一下吗?这将返回 1B21B3

    对于您问题的第二部分,您可以通过以下方式获取上述条目的时间戳:

    //p:entry[following-sibling::p:entry/p:msg/text()="Error1" and ./*/p:attrib[@name="Position"]]/@timestamp
    

    同样,这不会做你提到的“部分”事情。不幸的是,这超出了我(当前)对 xpath 的了解,这有点棘手。

    【讨论】:

    • 更新:我重新阅读了你的问题,我想我现在明白你想要什么了。
    • 谢谢盐山。这接近我需要的一部分。现在我只需要能够限制它返回一个结果。我想我将创建一个更通用但更清晰的新 xml 示例,以便读者也能理解我所指的“部分”。
    • 所以我一直在看你的例子,我认为我有获取时间戳的一般格式,但由于某种原因它没有拉回任何值。这是我目前所拥有的://p:entry[following-sibling::p:entry/p:msg/text()="Error1."]/*/p:entry[decendant::p:attrib[@name="Position"]]/@timestamp
    • 我想我需要把这个发布给 XQuery 人群。我只是尝试在 XQuery 脚本中运行上面的 xpath 并得到一个错误,说 SQL Server 2008 不支持“following-sibling”。
    • 嗯,如果不支持follow-sibling,那么你就不会走得太远!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    相关资源
    最近更新 更多