我有一个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处理上述情况或欢迎任何想法。
答案 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>