Двухфазная обработка: не выводить пустые теги при обработке XSLT 2.0 фазы-1 - PullRequest
9 голосов
/ 08 июля 2010

У меня есть несколько сложных преобразований XSLT 2.0. Я пытаюсь выяснить, есть ли универсальный способ убедиться, что пустые теги не выводятся. Итак ... концептуально, последний этап обработки, который рекурсивно удаляет все пустые теги. Я понимаю, что это можно сделать с помощью отдельного XSLT, который ничего не делал, кроме фильтрации пустых тегов, но мне нужно, чтобы все это было упаковано вместе в один.

1 Ответ

8 голосов
/ 08 июля 2010

Это преобразование XSLT 2.0 иллюстрирует, как может выполняться многопроходная (в данном случае двухпроходная) обработка :

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

 <xsl:template match="node()|@*" mode="#all">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*" mode="#current"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
   <xsl:variable name="vPass1">
     <xsl:apply-templates/>
   </xsl:variable>

   <xsl:apply-templates select="$vPass1/*" mode="non-empty"/>
 </xsl:template>

 <xsl:template match="text()[xs:integer(.) mod 2 eq 0]"/>

 <xsl:template match="*[not(node())]" mode="non-empty"/>
</xsl:stylesheet>

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

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

Создает результирующий документ при первом проходе (который фиксируется в переменной $vPass1), в котором все элементы <num> с содержимым, даже целым, удаляются из своего содержимого и пусты. Затем во втором проходе, примененном в определенном режиме, все пустые элементы удаляются.

Результат преобразования :

<nums>
   <num>01</num>
   <num>03</num>
   <num>05</num>
   <num>07</num>
   <num>09</num>
</nums>

Обратите внимание на использование режимов и специальных режимов #all и #current.

Обновление: ОП теперь хочет в комментарии удалить "рекурсивно" "все узлы, у которых нет непустого потомка".

Это может быть реализовано проще без явной рекурсии. Просто измените:

 <xsl:template match="*[not(node())]" mode="non-empty"/>

до:

 <xsl:template match="*[not(descendant::text())]" mode="non-empty"/>
...