xsl - позиция тега с текстом, смешанным в родительском - PullRequest
1 голос
/ 09 апреля 2011

В XSL 1.0 я пытаюсь различить следующие 2 сценария, которые оба происходят во входном XML, который мне нужно обработать, и каждый должен обрабатываться по-разному.

Сценарий 1

<tag1><tag2/> some text</tag1>

Сценарий 2

<tag1>some text <tag2/></tag1>

У меня есть шаблон, который соответствует уровню <tag2/>, в этом сценарии 1 я хочу игнорировать <tag2/>, в сценарии 2 я хочу вставить <br/> вместо <tag2/>.

Я искал здесь и в Google, но, похоже, не могу понять, как различать, основываясь на позиции <tag2/> в <tag1>.

Я изучил предшествующий брат и generate-id и попытался использовать что-то вроде: -

 not(
    generate-id(
       preceding-sibling::node()[1]
    )
  = generate-id(
       preceding-sibling::text()[1]
    )
 )

и

position()

из <tag2/>, похоже, здесь тоже не помогает, так как оба работают на уровне узла ??

Любые идеи приветствуются?

Спасибо Roger

Ответы [ 3 ]

1 голос
/ 09 апреля 2011

Посмотрите на эти шаблоны :

node()[1]

Это соответствует первому дочернему узлу.

node()[1][self::tag2]

Это соответствует дочернему узлу первого узла, который также является элементом tag2.

node()[not(self::text()[not(normalize-space())])][1][self::tag2]

Соответствует первому дочернему узлу, который не является текстовым узлом, состоящим только из пробелов, а также элементом tag2 (в случае, если вы сохраняете текстовый узел только пробелами, как и при вводе XHTML).

Я даю вам этот подход, потому что первый и второй паттерны streamable (preceding ось не может быть потоковой).

Примечание : второе должно быть переписано как node()[position() = 1 and self::tag2].

0 голосов
/ 09 апреля 2011

Более простое и фундаментальное решение :

<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="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match=
  "node()[self::tag2 and position()=1]"/>
 <xsl:template match=
  "node()[self::tag2 and position()=2]">
  <br/>
 </xsl:template>
</xsl:stylesheet>

При применении к этому документу XML :

<tag1><tag2/> some text</tag1>

дает желаемый, правильный результат:

<tag1> some text</tag1>

Применительно к этому документу :

<tag1>some text <tag2/></tag1>

снова выдается желаемый, правильный ответ :

<tag1>some text <br/>
</tag1>

Объяснение

  1. Правило идентификации (шаблон) копирует каждый узел как есть.

  2. Первый шаблон, который переопределяет правило идентификации, соответствует любому узлу, имя которого tag2 и позиция которого в списке узлов равна 1. Он не имеет тела, поэтому элемент tag2 игнорируется.

  3. Второй шаблон, который переопределяет правило идентификации, аналогичен первому, но позиция соответствующего узла tag2 должна быть 2. В этом случае он заменяется на <br/>.

0 голосов
/ 09 апреля 2011

Следующая таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="tag2[preceding-sibling::text()]">
        <br/>
    </xsl:template>
</xsl:stylesheet>

На этом входе:

<items>
    <tag1><tag2/>some text</tag1>
    <tag1>some text <tag2/></tag1>
</items>

Производит:

some text
some text <br/>

Более сложное решение потребовало бы дополнительной информации ожелаемый вывод.

...