范围内没有命名空间的 XPath 3.0 序列化

XPath 3.0 Serialize without Namespaces in Scope

虽然回答了 , it occurred to me that I know how to use the 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 元素,删除作用域中的名称空间,然后序列化这个修改后的元素。但这似乎是一个相当麻烦的解决方案。我的问题是:

使用 serialize() 函数序列化 XML 元素而不同时序列化范围内未使用的命名空间声明的规范方法是什么?


在 Oxygen 中使用 Saxon-EE 9.6.0.7 进行测试。

序列化将始终为您提供您正在序列化的数据模型的忠实表示。如果你想修改数据模型,那就叫做转换。 运行 删除不需要的命名空间的转换,然后序列化结果。

Michael Kay 已经给出了正确答案,我已经接受了。这只是为了充实他的评论。通过

Run a transformation to remove the unwanted namespaces, then serialize the result.

他的意思是在调用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>