Xpath: выберите узел, но не конкретные дочерние элементы - PullRequest
8 голосов
/ 19 августа 2011

У меня есть структура, похожая на следующую:

<page id='1'>
  <title>Page 1</title>    
  <page id='2'>
    <title>Sub Page 1</title>
  </page>
  <page id='3'>
    <title>Sub Page 2</title>
  </page>    
</page>
<page id='4'>
  <title>Page 2</title>
</page>

Мне нужно выбрать страницу по идентификатору, но если на этой странице есть страницы-потомки, я не хочу возвращать эти элементы, но мне нужны другие элементы этой страницы. Если я выбираю Page 1, я хочу вернуть заголовок, но не дочерние страницы ...

//page[@id=1]

Выше приведена страница 1, но как исключить подстраницы? Кроме того, на странице может быть любое произвольное количество элементов.

//page[@id=1]/*[not(self::page)]

Я обнаружил, что это дает мне данные, которые я хочу. Однако эти данные возвращаются как массив объектов с одним объектом на элемент и, по-видимому, исключают имена элементов ???. Я использую PHP SimpleXML для того, что он стоит.

Ответы [ 3 ]

8 голосов
/ 19 августа 2011

Использование :

//page[@id=$yourId]/node()[not(self::page)]

Выбирает все узлы, которые не являются page и являются потомками любого page в документе, строковое значение которого id Атрибут равен строке, содержащейся в $yourId (скорее всего, вы бы заменили $yourId выше конкретной, желаемой строкой, такой как '1').

Вот простой XSLTпроверка на основе :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pId" select="3"/>

 <xsl:template match="/">
     <xsl:copy-of select="//page[@id=$pId]/node()[not(self::page)]"/>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к предоставленному XML-документу (заключенному в один верхний узел, чтобы сделать его правильно сформированным):

<pages>
    <page id='1'>
        <title>Page 1</title>
        <page id='2'>
            <title>Sub Page 1</title>
        </page>
        <page id='3'>
            <title>Sub Page 2</title>
        </page>
    </page>
    <page id='4'>
        <title>Page 2</title>
    </page>
</pages>

получен требуемый, правильный результат :

<title>Sub Page 2</title>

Примечание : Одно из предположений состоит в том, что значение id однозначно определяетpage.Если это не так, предлагаемое выражение XPath выберет все page элементов, чей атрибут id имеет строковое значение $yourId.

Если это так и толькодолжен быть выбран один элемент page, OP должен указать, какой из множества элементов page с этим id должен быть выбран.

Например, это может быть первый :

(//page[@id=$yourId]/node()[not(self::page)])[1]

или последний :

(//page[@id=$yourId]/node()[not(self::page)])[last()]

или ...

1 голос
/ 19 августа 2011

Если вас интересует только элемент title, это сработает:

//page[@id=1]/title

Если, однако, вам нужны другие подэлементы страницы, я не уверен, что XPath - правильный инструмент для вас. Больше похоже на то, для чего подойдет XSLT, поскольку на самом деле вы трансформируете свои данные.

0 голосов
/ 19 августа 2011

Если страница всегда имеет заголовок:

//page[@id='1']/*[not(boolean(./title))]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...