xpath-如果节点包含文本,则获取节点的同级值

时间:2019-03-06 13:57:45

标签: xml xpath

我有这个XML结构:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <a xmlns="#">
             <b>
                <c>
                   <d>dd</d>
                   <e>ee</e>
                   <f>ff</f>
                   <g>gg</g>
                </c> 
                <c>
                   <d>ddd</d>
                   <e>eee</e>
                   <f>fff</f>
                   <g>ggg</g>
                </c> 
                <c>
                   <d>dddd</d>
                   <e>eeee</e>
                   <f>ffff</f>
                   <g>gggg</g>
                </c>  
             </b>
       </a>
     </soap:Envelope>

我的目标是获取所有<f>,其中包含特定的字符串(在此示例中,请说“ f”)。 这是通过以下方式完成的:

$result = $xml->xpath("//*[text()[contains(.,'f')]]");

此示例返回一个数组,如下所示:

    array (3)
      0 => SimpleXMLElement #f4ff
         0 => "ff" (2)
      1 => SimpleXMLElement #617e
         0 => "fff" (3)
      2 => SimpleXMLElement #863a
         0 => "ffff" (4)

现在,这一切都很好。现在出现了问题。我需要的是<d>的值,如果<f>包含“ f”,但是我都需要在同一数组中使用它们,就像这样:

 array (3)
      0 => SimpleXMLElement #f4ff
         0 => "dd" (2)
         1 => "ff" (2)
      1 => SimpleXMLElement #617e
         0 => "ddd" (3)
         0 => "fff" (3)
      2 => SimpleXMLElement #863a
         0 => "ffff" (4)
         0 => "ffff" (4)

我希望我的问题是可以理解的。有人可以建议我如何实现这一目标吗?

2 个答案:

答案 0 :(得分:0)

  

如果<d>包含<f>,我需要的是"f"的值

这很简单:

//f[contains(. 'f')]/../d
  

但我都需要在同一阵列中

那不是那么容易。您可以这样做:

//f[contains(. 'f')]/../*[self::f or self::d]

这将为您提供<f><d>的列表,其中<f>包含"f",但是不会将它们“成组”成对。使用单个XPath表达式您无法选择的任何东西-平面节点列表是XPath唯一可以给您的东西。根据输入数据的正常程度,这可能就足够了。

如果需要“ pairs”上下文,请拆分操作。选择所有<c>包含<f>的{​​{1}}:

"f"

,然后在每个步骤中分别选择//c[contains(f, 'f')] <f>

<d>

请注意,XPath按文档顺序返回节点。如果这在您的输入中不可预测,请单独选择节点,而不要使用单个表达式。

答案 1 :(得分:0)

答案是:

$result = $xml->xpath("//*[text()[contains(.,'f')]]/parent::*");

感谢所有试图思考问题的人。祝你有美好的一天。