Сериализация XPath 3.0 без пространств имен в области видимости

Отвечая на этот вопрос, я понял, что знаю, как использовать XSLT 3.0 (XPath 3.0) serialize(), но я не знаю, как избежать сериализации пространств имен которые находятся в сфере действия. Вот минимальный пример:

Ввод XML

<?xml version="1.0" encoding="UTF-8" ?>
<ci:cichlids xmlns:ci="http://www.cichlids.com">
    <cichlid id="1">
        <name>Zeus</name>
        <color>gold</color>
        <teeth>molariform</teeth>
        <breeding-type>lekking</breeding-type>
    </cichlid>
</ci:cichlids>

Таблица стилей XSLT 3.0

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization"
    xmlns:ci="http://www.cichlids.com">

    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

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

    <xsl:template match="/ci:cichlids/cichlid">
        <xsl:variable name="serial-params">
            <output:serialization-parameters>
                <output:omit-xml-declaration value="yes"/>
            </output:serialization-parameters>
        </xsl:variable>
        <xsl:value-of select="serialize(., $serial-params/*)"/>
    </xsl:template>

</xsl:stylesheet>

Фактический результат

<?xml version="1.0" encoding="UTF-8"?>
<ci:cichlids xmlns:ci="http://www.cichlids.com">
    &lt;cichlid xmlns:ci="http://www.cichlids.com" id="1"&gt;
        &lt;name&gt;Zeus&lt;/name&gt;
        &lt;color&gt;gold&lt;/color&gt;
        &lt;teeth&gt;molariform&lt;/teeth&gt;
        &lt;breeding-type&gt;lekking&lt;/breeding-type&gt;
    &lt;/cichlid&gt;
</ci:cichlids>

Процесс сериализации включал объявление пространства имен, которое находится в области действия для элемента cichlid, хотя оно не используется в этом элементе. Я хотел бы удалить это объявление и сделать вывод похожим на

Ожидаемый результат

<?xml version="1.0" encoding="UTF-8"?>
<ci:cichlids xmlns:ci="http://www.cichlids.com">
    &lt;cichlid id="1"&gt;
        &lt;name&gt;Zeus&lt;/name&gt;
        &lt;color&gt;gold&lt;/color&gt;
        &lt;teeth&gt;molariform&lt;/teeth&gt;
        &lt;breeding-type&gt;lekking&lt;/breeding-type&gt;
    &lt;/cichlid&gt;
</ci:cichlids>

Я знаю, как изменить элемент cichlid, удалив пространства имен в области видимости, и вместо этого сериализовать этот измененный элемент. Но это кажется довольно громоздким решением. Мой вопрос:

Каков канонический способ сериализации элемента XML с помощью serialize() без сериализации неиспользуемых объявлений пространств имен, находящихся в области видимости?


Тестирование с Saxon-EE 9.6.0.7 из Oxygen.


person Mathias Müller    schedule 23.02.2016    source источник


Ответы (2)


Сериализация всегда даст вам точное представление модели данных, которую вы сериализуете. Если вы хотите изменить модель данных, это называется трансформацией. Запустите преобразование, чтобы удалить ненужные пространства имен, а затем сериализуйте результат.

person Michael Kay    schedule 24.02.2016
comment
Спасибо за Ваш ответ. Если бы я сериализовал результат обычного XSLT-преобразования, я мог бы использовать exclude-result-prefixes для удаления неиспользуемых пространств имен, и мне не пришлось бы напрямую изменять модель данных. Есть ли средство, сравнимое с exclude-result-prefixes при использовании serialize()? - person Mathias Müller; 24.02.2016
comment
@MathiasMüller, нет, если ввод опубликован, и ваш XSLT подойдет, например. <xsl:template match="/"><xsl:copy-of select="//cichlid"/></xsl:template>, то использование exclude-result-prefixes не поможет скопировать пространства имен в области действия из ввода в сериализуемый вывод. Вам нужно убедиться, что вы используете <xsl:copy-of select="//cichlid" copy-namespaces="no"/>. То же самое будет необходимо, если вы хотите использовать функцию serialize, вам нужно будет сначала преобразовать ввод, чтобы избавиться от пространств имен в области видимости. exclude-result-prefixes помогает только с пространствами имен в XSLT. - person Martin Honnen; 24.02.2016
comment
@MartinHonnen Спасибо, теперь я понял. - person Mathias Müller; 24.02.2016

Майкл Кей уже дал правильный ответ, и я его принял. Это просто для конкретизации его комментариев. По

Запустите преобразование, чтобы удалить ненужные пространства имен, а затем сериализуйте результат.

он имеет в виду применение преобразования, подобного следующему, перед вызовом serialize():

Таблица стилей XSLT

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization"
    xmlns:ci="http://www.cichlids.com">

    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

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

    <xsl:variable name="cichlid-without-namespace">
        <xsl:copy-of copy-namespaces="no" select="/ci:cichlids/cichlid"/>
    </xsl:variable>

    <xsl:template match="/ci:cichlids/cichlid">
        <xsl:variable name="serial-params">
            <output:serialization-parameters>
                <output:omit-xml-declaration value="yes"/>
            </output:serialization-parameters>
        </xsl:variable>
        <xsl:value-of select="serialize($cichlid-without-namespace, $serial-params/*)"/>
    </xsl:template>

</xsl:stylesheet>

Вывод XML

<?xml version="1.0" encoding="UTF-8"?>
<ci:cichlids xmlns:ci="http://www.cichlids.com">
    &lt;cichlid id="1"&gt;
        &lt;name&gt;Zeus&lt;/name&gt;
        &lt;color&gt;gold&lt;/color&gt;
        &lt;teeth&gt;molariform&lt;/teeth&gt;
        &lt;breeding-type&gt;lekking&lt;/breeding-type&gt;
    &lt;/cichlid&gt;
</ci:cichlids>
person Mathias Müller    schedule 24.02.2016