2010-07-07 4 views
8

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

+0

Отличный вопрос (+1). См. Мой ответ для подробного решения. –

ответ

8

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

<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> с содержимым даже интуитивно понятны r удаляются из их содержимого и пусты. Затем, во втором проходе, применяемом в определенном режиме, все пустые элементы удаляются.

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

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

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

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

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

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

к:

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

Это отвечает на общий вопрос, но есть определенная часть, которую он пропускает - рекурсивно удаляет все пустые теги ... поэтому мне просто нужно изменить «* [not (node ​​())]» на соответствующее выражение, которое означает все узлы, у которых нет непустого потомка. – mentics

+0

@taotree В следующий раз лучше сформулируйте свой вопрос. :) Я думаю, что лучше сделать это новое требование отдельным вопросом - это тоже отличный вопрос. Вы можете использовать для шаблона соответствия пустого шаблона: '* [not (descendant :: text())]' –

+0

@taotree Обновлен ответ, чтобы отразить ваше новое требование ... :) –

 Смежные вопросы

  • Нет связанных вопросов^_^