Отличительные значения по наборам узлов XSLT - PullRequest
2 голосов
/ 13 января 2012

Еще раз о различных узлах (на основе значений атрибутов) в наборе узлов. Представьте, что у вас есть следующая структура:

<struct>
  <a>
    <x id="1">a_1</x>
    <x id="2">a_2</x>
    <x id="3">a_3</x>
  </a>
  <b inherits="a">
    <x id="2">b_2</x>
  </b>
</struct>

<struct/> может содержать несколько элементов, таких как <b/>, которые наследуют один и тот же <a/>. В то же время допускается несколько элементов, таких как <a/>. Порядок <a/> с и <b/> с является произвольным. Наследование одноуровневое.

Вопрос : Как создать одиночный XPath, который выбирает следующий набор узлов для данного <b/>:

<x id="1">a_1</x>
<x id="2">b_2</x>
<x id="3">a_3</x>

Обратите внимание на значение b_2 во второй строке.

Какие-нибудь решения для этого?

Обновление:

Полученный XPath должен иметь следующую форму: b[(magic_xpath)[@id=2]='b_2'], где magic_xpath выбирает различные <x/> s из <a/> s и <b/> s.

Реальная жизнь <struct/> может выглядеть так:

<struct>
  <a>
    <x id="1">a_1</x>
    <x id="2">a_2</x>
    <x id="3">a_3</x>
  </a>
  <b inherits="a">
    <x id="2">I don't match resulting XPath</x>
  </b>
  <b inherits="a">
    <x id="2">b_2</x>
  </b>
</struct>

1 Ответ

1 голос
/ 13 января 2012

Используйте

  $vB/x
 |
  /*/*[name() = $vB/@inherits]
                /x[not(@id = $vB/x/@id)]

, где $vB определяется как элемент b.

Выбирает объединение всех элементов b/x и всех дочерних элементов x (с атрибутом id, который не равен ни одному атрибуту b/x/@id) из элементов struct/* (дочерних элементов struct), чьи name это значение b/@inherits.

Или, по запросу ОП в комментарии - без переменных:

  /*/b/x
 |
  /*/*[name() = /*/b/@inherits]
                /x[not(@id = /*/b/x/@id)]

Полная проверка на основе XSLT :

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

 <xsl:template match="/">
     <xsl:copy-of select=
     "/*/b/x
     |
      /*/*[name() = /*/b/@inherits]
                    /x[not(@id = /*/b/x/@id)]

   "/>
 </xsl:template>
</xsl:stylesheet>

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

<struct>
    <a>
        <x id="1">a_1</x>
        <x id="2">a_2</x>
        <x id="3">a_3</x>
    </a>
    <b inherits="a">
        <x id="2">b_2</x>
    </b>
</struct>

оценивается одно выражение XPath и выводятся выбранные узлы :

<x id="1">a_1</x>
<x id="3">a_3</x>
<x id="2">b_2</x>
...