XSL转换,其中输入xml文件已定义或不存在xmlns

时间:2014-01-17 18:13:52

标签: xml xslt xslt-1.0

我有一个xml输入,有时可能有或没有定义xmlns。 如何通过一个xsl成功转换来解决这种情况? 以下是两种情况下的输入和xsl (1.0)

输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<input version="2.1">
    <Data>
        <Object class="PM" operation="create" name="japan">
            <p name="Active">1</p>
        </Object>
        <Object class="AM" operation="create" name="india">
            <p name="Active">0</p>
        </Object>
    </Data>
</input>

没有名称空间定义的XSL:

<?xml version="1.0"?>
<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">
    <xsl:template match="Data">
        <xsl:copy>
            <xsl:apply-templates select="Object[@class='PM' or @class='AM']">
                <xsl:sort select="@name"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="Object[not(@class='PM' or @class='AM')]"/>
        </xsl:copy>
    </xsl:template>

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

    <xsl:template match="Object[@operation = 'create' ]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="class">
                <xsl:value-of select="concat(@class,'/TIME')"/>
            </xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输入xml并定义了命名空间:

<?xml version="1.0" encoding="UTF-8"?>
<input version="2.1" xmlns="xyz.xsd">
    <Data>
        <Object class="PM" operation="create" name="japan">
            <p name="Active">1</p>
        </Object>
        <Object class="AM" operation="create" name="india">
            <p name="Active">0</p>
        </Object>
    </Data>
</input>

虽然xslt没有抛出错误,但输出没有按预期转换:(

如何使用单个xsl处理上述情况或欢迎任何想法。

3 个答案:

答案 0 :(得分:3)

如果你需要处理任何具有特定本地名称的元素而不管XSLT 1.0中的命名空间,那么你需要使用像*[local-name() = 'Object']这样的成语,或者你可以将你的模式基于结构而不是名称(即,而不是“匹配一个名为对象的元素”,你说“匹配从根目录下降三级的任何元素”):

<?xml version="1.0"?>
<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">
    <xsl:template match="/*/*">
        <xsl:copy>
            <xsl:apply-templates select="*[@class='PM' or @class='AM']">
                <xsl:sort select="@name"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="*[not(@class='PM' or @class='AM')]"/>
        </xsl:copy>
    </xsl:template>

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

    <xsl:template match="/*/*/*[@operation = 'create' ]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="class">
                <xsl:value-of select="concat(@class,'/TIME')"/>
            </xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

编写XSLT,这样如果输入不在命名空间中,它首先要做的是创建命名空间中IS的数据副本(反之亦然)。然后其余的代码不需要担心区别。

答案 2 :(得分:1)

  

是的,现在只有一个名称空间或它不存在..还没有   碰到了随意的。

在这种情况下,您可以为命名空间定义前缀,并调整样式表以“并行”调用任何元素的两个版本:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xyz="http://xyz.xsd">

<xsl:template match="Data | xyz:Data">
    <xsl:copy>
        <xsl:apply-templates select="Object[@class='PM' or @class='AM'] | xyz:Object[@class='PM' or @class='AM']">
            <xsl:sort select="@name"/>
        </xsl:apply-templates>
        <xsl:apply-templates select="Object[not(@class='PM' or @class='AM')] | Object[not(@class='PM' or @class='AM')]"/>
    </xsl:copy>
</xsl:template>

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

<xsl:template match="Object[@operation = 'create' ] | Object[@operation = 'create' ]">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="class">
            <xsl:value-of select="concat(@class,'/TIME')"/>
        </xsl:attribute>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>