Как выбрать различные значения из документа XML с помощью XPATH?

Как я могу выбрать только отдельные элементы для XML-документа с помощью XPATH? Я пытался использовать функцию "отдельные значения", но по какой-то причине он не работал.

XML похож на следующий:

<catalog>

<product>
<size>12</size>
<price>1000</price>
<rating>1</rating>
</product>

<product>
<size>10</size>
<price>1000</price>
<rating>1</rating>
<year>2010</year>
</product>

</catalog>

Так что я хочу получить список отдельных детей из всех элементов продукта. В данном примере это будет - размер, цена, рейтинг, год Мой xpath был чем-то вроде: distinct-values ​​(catalog/product/*)

Ответ 1

В XPath 2.0:

distinct-values(/*/*/*/name(.))

В XPath 1.0 это невозможно создать с помощью одного выражения XPath.

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

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/">
   <xsl:for-each select=
   "/*/*/*[not(../following::*/*
                       [not(name() = name(current()))]
               )
           ]">
     <xsl:value-of select="concat(name(), ' ')"/>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному XML-документу, желаемый результат создается:

size price rating year

Более эффективное преобразование XSLT 1.0 с использованием клавиш:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kpchildByName"
  match="product/*" use="name()"/>

 <xsl:template match="/">
   <xsl:for-each select=
   "/*/*/*
         [generate-id()
         =
          generate-id(key('kpchildByName', name())[1])
          ]">
     <xsl:value-of select="concat(name(), ' ')"/>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Ответ 2

distinct-values() доступен в XPath 2.0. Вы используете это?

Если distinct-values() недоступен, стандартный способ получения отдельных значений - использовать not(@result = preceding:: @result) для получения уникального @result. Это даст вам только первое событие.

Ответ 3

Вам нужны различные значения имен элементов - что-то вроде:

distinct-values($catalog/product/*/name(.))