XPath 3.0在Scope中没有命名空间的序列化

时间:2016-02-23 22:32:08

标签: xslt serialization xslt-3.0 xpath-3.0

在回答this question时,我突然意识到我知道如何使用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元素的规范方法是什么,而不是序列化范围内未使用的命名空间声明?

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

2 个答案:

答案 0 :(得分:3)

序列化将始终忠实地表示您要序列化的数据模型。如果要修改数据模型,则称为转换。运行转换以删除不需要的命名空间,然后序列化结果。

答案 1 :(得分:1)

迈克尔凯已经给出了正确答案,我接受了。这只是为了充实他的评论。由

  

运行转换以删除不需要的命名空间,然后序列化结果。

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