需要一个复杂的Xpath使用兄弟的孩子,祖先

时间:2012-09-25 18:35:37

标签: xpath xquery-sql tree-traversal siblings

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

所以给定以下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>
  • <p:attributes>个父标记可以有多个<p:attrib>子标记)
  • <p:event>代码只能有一个<p:msg>代码

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

接下来,我需要我抓住的p:msg / Error1孩子的父母的时间戳属性值。因此,找到位置,然后找到祖父Position标记的时间戳属性值。

因此,对于此示例,我应该只能检索以下值:

Value

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

我知道有点混乱。我还需要确保只抓取一个实例,因为我使用XQuery从数据库中获取数据,每个表达式都必须产生一个奇异的值。

我可以使用以下1B3来获取与2012-12-31T12:12:12相关联的第一个时间戳:p:msg

但似乎无法恢复树以获得其他值。

我可以获得p:attrib grand-children的p:event事件的所有时间戳:Error1

但我似乎无法将其限制在跟随它的'Error1'之后。我不能把我的选择基于位置。我必须首先以内容为基础。

奖金问题

如何在日志文件的下一个实例上再次执行此操作? (不只是第二条//p:entry[descendant::p:msg='Error1.'][1]/@timestamp消息,下一次在日志文件中向下显示//p:entry[descendant::p:attrib[@name=''Position'']]/@timestamp)[1] msg以显示下一个“父/兄弟”匹配项。一旦我得到上述问题的答案,这可能是显而易见的。

1 个答案:

答案 0 :(得分:1)

<强>已更新

好的,我想我得到了这个。这是第一个答案:

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

这是从p:msg标记开始返回,这样可以更轻松地选择前一个父{{1}的第一个(那里是[1])满足条件的标签,它们有一个名为p:entry的孙p:attrib

获取时间戳只是一点点简单:

Position

尝试一下,看看你的想法。

原始回答

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

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

这将得到

  

具有相应名称属性Position的value属性的值,但仅当grand-parent的兄弟p:条目具有子句p:msg且文本为Error1时才会显示。

但是当你说“它需要留在那个部分”时,我不知道你的意思。你能澄清一下吗?这将返回//p:entry[following-sibling::p:entry/p:msg/text()="Error1"]/*/p:attrib[@name="Position"]/@value 1B2

对于问题的第二部分,您可以使用以下内容获取上述条目的时间戳:

1B3

但是,这不会做你提到的“部分”事情。不幸的是,除了我(当前)对xpath的了解之外,这有点棘手。