Выберите единственный первый соответствующий узел в XPath - PullRequest
9 голосов
/ 29 января 2010

У меня есть следующий XML:

<parent>
   <pet>
      <data>
         <birthday/>
      </data>
   </pet>
   <pet>
      <data>
         <birthday/>
      </data>
   </pet>
</parent> 

А теперь я хочу выбрать первый элемент дня рождения с помощью parent//birthday[1], но это возвращает оба элемента дня рождения, потому что оба они - первый ребенок своих родителей.

Как я могу выбрать только первый элемент дня рождения всего документа, где бы он ни находился. Я пробовал parent//birthday[position()=1], но это тоже не работает.

Ответы [ 5 ]

14 голосов
/ 29 января 2010

Вы имеете в виду (обратите внимание на круглые скобки!)

(/parent/pet/data/birthday)[1]

или более короткий, но менее конкретный вариант:

(/*/*/*/birthday)[1]
(//birthday)[1]

или, более семантически, "1007 *" день рождения первого питомца ":

/parent/pet[1]/data/birthday

или, если не у всех домашних животных, есть записи на день рождения, "день рождения первого домашнего животного, для которого установлен день рождения" :

/parent/pet[data/birthday][1]/data/birthday

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

Пояснение:

  • /parent/pet/data/birthday[1] выделяет все <birthday> узлы, которые являются первыми в соответствующих родительских узлах (<data> узлы), по всему документу
  • (/parent/pet/data/birthday)[1] выбирает все <birthday> узлы и из этих (это то, что делают круглые скобки, они создают промежуточный набор узлов), он берет первый
4 голосов
/ 30 января 2010

К вашему сведению: вы можете визуализировать результаты различных запросов Xpath с помощью (бесплатного) инструмента XPathVisualizer . Работает только на Windows.

alt text

1 голос
/ 29 января 2010

Хорошо, я признаю, что это ужасно, и должен быть лучший способ, но, похоже, он работает.

/*/*[descendant::birthday and not(preceding-sibling::*[descendant::birthday])]

Я ищу все элементы второго уровня в дереве, у которых есть элемент-потомок с именем Birthday, у которого нет предшествующего элемента-брата, у которого есть элемент Birthday в качестве потомка.

0 голосов
/ 29 января 2010
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <xsl:variable name="birthdays" select="//birthday"/>
        <xsl:value-of select="$birthdays[1]"/>
    </xsl:template>

</xsl:stylesheet>
0 голосов
/ 29 января 2010

1001 * попробовать *

//birthday[position()=1]

// находит узлы независимо от того, где они находятся в иерархии

Вы могли бы также сделать

pet[position()=1]/data/birthday
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...