我有一个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 或任何想法来处理上述情况。
如果您需要处理具有特定本地名称的任何元素,而不管 XSLT 1.0 中的命名空间如何,那么您需要使用像 *[local-name() = 'Object']
这样的习惯用法,或者你可以将模式基于结构而不是名称(即,不是"匹配名为 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>
编写 XSLT,以便在输入不在命名空间中时它要做的第一件事是创建命名空间中 IS 的数据的副本(反之亦然)。然后,代码的其余部分无需担心区别。
是的,目前只有一个命名空间或不存在。还没有 遇到随机的。
在这种情况下,您可以为命名空间定义一个前缀,并调整样式表以"并行"调用任何元素的两个版本:
<?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>