xsl для рекурсивного копирования только некоторых элементов и удаления некоторых потомков - PullRequest
3 голосов
/ 02 сентября 2011

Я хотел бы преобразовать

<?xml version="1.0" ?>
<mydoc>
    <file>
        <colors>
            <blue />
            <red />
            <green />
        </colors>
        <secret>
            <username />
            <password />
        </secret>
    </file>
</mydoc>

в

<?xml version="1.0" ?>
<colors>
  <blue />
  <red />
</colors>

В простом английском я хотел бы рекурсивно скопировать элемент colors, включая текст, игнорировать остальную часть документа XML и отбросить зеленый элемент.

Существуют решения, работающие с приведенным выше примером, но они потерпят неудачу, если XML немного отличается. Например, добавив элемент nest в элемент color или элемент other , который не входит в иерархию элемента color или текст, находящийся в области действия элемента color (ХОРОШИЙ ТЕКСТ), а другой - вне его области (ПЛОХОЙ ТЕКСТ).

<?xml version="1.0" ?>
<mydoc>
    <file>
        <colors>
            <nest>
              <blue />
              <red />
              <green />
            </nest>
            GOOD TEXT
        </colors>
        <secret>
            <username />
            <password />
        </secret>
        BAD TEXT
    </file>
    <other>BAD TEXT TWO</other>
</mydoc>

Меня больше всего интересует решение, которое является общим и не адаптировано к представленным здесь примерам.

Ответы [ 2 ]

2 голосов
/ 02 сентября 2011

Это новое преобразование достаточно общее, чтобы копировать элементы цветов независимо от того, является ли их родительский элемент .

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/mydoc/file/colors">
        <xsl:variable name="colors_parent"
            select="local-name(.//green/parent::*)"/>
        <xsl:copy>
            <xsl:copy-of 
                select=".//*[local-name()=$colors_parent]/*[not(self::green)]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:stylesheet>

Я также исключил все возможные текстовые элементы. Пока не ясно, хотите ли вы сохранить текстовый узел «ХОРОШИЙ ТЕКСТ». Однако теперь вам будет очень легко адаптировать преобразование к новым требованиям. Например, если вы хотите сохранить любой текстовый узел в элементе colors , вы можете изменить это преобразование:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/mydoc/file/colors">
        <xsl:variable name="colors_parent"
            select="local-name(.//green/parent::*)"/>
        <xsl:copy>
            <xsl:copy-of 
                select=".//*[local-name()=$colors_parent]/*[not(self::green)]
                      | .//text()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:stylesheet>

Правило использования идентификатора (оно копирует элемент nest )

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="mydoc">
        <xsl:apply-templates select="file/colors"/>
    </xsl:template>

    <xsl:template match="green"/>

</xsl:stylesheet>
1 голос
/ 02 сентября 2011
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>

    <xsl:template match="/">
        <colors>
            <xsl:apply-templates select="//colors/*[not(self::green)]"/>
        </colors>
    </xsl:template>

    <xsl:template match="*">
        <xsl:copy-of select="."/>
    </xsl:template>

</xsl:stylesheet>

Выход:

<colors>
    <blue />
    <red />
</colors>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...