xsl: преобразовать теги пространства имен - PullRequest
2 голосов
/ 06 октября 2011

У меня есть xsl, который копирует файл xml и переименовывает корневой тег.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:abc="http://example.com">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

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

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

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

</xsl:stylesheet>

Это прекрасно работает, но когда я раскомментирую последний блок для обработки некоторых тегов с пространством имен, я получаю сообщение об ошибке, чточто-то не так с оператором копирования.Как я могу сопоставить и преобразовать теги пространства имен?

Ответы [ 3 ]

2 голосов
/ 06 октября 2011

Вероятно, вы получаете ошибку, потому что элемент abc:set имеет атрибуты, а ваш шаблон, соответствующий abc:set, создает "голые" атрибуты, которые не прикреплены к элементу.

Поскольку вы не копируете элемент abc:set (или не создаете элемент) в соответствии с шаблоном для abc:set, когда apply-templates внутри этого шаблона применяет шаблоны к выбранным abc:set/@* и abc:set/node() затем атрибуты соответствуют шаблону идентификации и будут скопированы вперед.

Вы можете проверить, является ли это проблемой, убрав @* из оператора select для apply-templates, например:

<xsl:template match="abc:set">
    <xsl:apply-templates select="node()"/>
</xsl:template>

Приведенный выше шаблон будет обрабатывать только дочерние узлы abc:set.

Если ваше намерение состояло в том, чтобы просто скопировать abc:set, то вам не нужен конкретный шаблон, соответствующий этому элементу. Шаблон идентичности будет соответствовать ему и обрабатывать его для вас.

2 голосов
/ 06 октября 2011

Если вы действительно хотите удалить элемент abc:set, но сохранить поддерево, корневым элементом которого он является, то замените :

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

на:

<xsl:template match="abc:set">
    <xsl:apply-templates/>     
</xsl:template>

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

Код замены не обрабатывает никаких атрибутов соответствующего элемента abc:set.

2 голосов
/ 06 октября 2011

Я не знаю, что именно вы пытаетесь достичь. Ваш вопрос немного абстрактен. Однако ваш атрибут соответствия правильный. Но сейчас нет никакой разницы, что:

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

делает и что это:

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

делает. Если вы просто хотите скопировать все, тогда достаточно первого шаблона, включая теги с пространствами имен. В противном случае, я думаю, вам нужно будет сделать что-то по-другому при сопоставлении вашего тега пространства имен. Если это так, то вам не нужно повторно вызывать шаблон совпадения. например :

<!--Do something with abc:set-->
<xsl:template match="abc:set">
    <setchanged name="{@name}"/>
</xsl:template>

Будьте уверены, что это будет соответствовать всем тегам abc: set и применить к ним преобразование.

...