xpath - получить значение родственного узла, если узел содержит текст - PullRequest
0 голосов
/ 06 марта 2019

У меня есть такая структура 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 голосов
/ 07 марта 2019

Ответы:

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

Спасибо всем, кто пытался подумать о проблеме. Хорошего дня.

0 голосов
/ 07 марта 2019

Что мне нужно, это значение <d>, если <f> содержит "f"

Это просто:

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

ноМне нужно это как в одном массиве

Это не так просто.Вы можете сделать это:

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

, который даст вам список <f> s и <d> s, где <f> содержит "f", но они не будут "сгруппированы" в пары.Ничего из того, что вы можете выбрать с помощью одного выражения XPath, не будет - списки плоских узлов - это единственное, что XPath может вам дать.В зависимости от того, насколько регулярны ваши входные данные, это может быть достаточно.

Если вам нужен контекст «пар», разбейте операцию.Выберите все <c>, где <f> содержит "f":

//c[contains(f, 'f')]

и для каждого из них выберите <f> и <d> на втором шаге:

./*[self::f or self::d]

Обратите внимание, что XPath возвращает узлы в порядке документов.Если это не предсказуемо при вводе, выбирайте узлы индивидуально, а не одним выражением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...