我有XML生成不同的命名空间,因此如何避免在xsl中使用名称空间并使用单个xsl获得低于结果的结果。或者我可以使用任何狂野的字符,如http://namesapce//example/*/format
输入1:
<dynamic>
<rpc xmlns="http://namespace/example/123/format" >
<route>
<table>
<tablename>employee</tablename>
<count>20</count>
</table>
<table>
<tablename>employee</tablename>
<count> 21</count>
<rt> 1</rt>
<rt> 2</rt>
<rt> 3</rt>
<rt> 4</rt>
</table>
<table>
<tablename>dept</tablename>
<count>20</count>
<rt> a</rt>
<rt> b</rt>
<rt> c</rt>
</table>
<table>
<tablename>employee</tablename>
<count> 21</count>
<rt> 5</rt>
<rt> 6</rt>
<rt> 7</rt>
<rt> 8</rt>
</table>
<table>
<tablename>dept</tablename>
<count>44</count>
<rt> d</rt>
<rt> e</rt>
<rt> g</rt>
</table>
</route>
</rpc>
</dynamic>
输入2:
<dynamic>
<rpc xmlns="http://namespace/example/567/format" >
<route>
<table>
预期产出1:
<?xml version="1.0" encoding="UTF-8"?>
<dynamic>
<rpc xmlns="http://namespace/example">
<route>
<table>
<tablename>employee</tablename>
<count>20</count>
<rt> 1</rt>
<rt> 2</rt>
<rt> 3</rt>
<rt> 4</rt>
<rt> 5</rt>
<rt> 6</rt>
<rt> 7</rt>
<rt> 8</rt>
</table>
<table>
<tablename>dept</tablename>
<count>20</count>
<rt> a</rt>
<rt> b</rt>
<rt> c</rt>
<rt> d</rt>
<rt> e</rt>
<rt> g</rt>
</table>
</route>
</rpc>
</dynamic>
xml 2的输出2也包含名称空间,这个xsl应该能够处理任何类型的这种XML。
<?xml version="1.0" encoding="UTF-8"?><dynamic>
<rpc xmlns="http://namespace/example/567/format">
<route>
答案 0 :(得分:1)
进行两阶段转换。阶段1:标准化命名空间。阶段2:进行真正的转型工作。
这样可以最大限度地减少必须处理变体名称空间的代码量。
您可以使用
等代码规范化名称空间<xsl:template match="old:*" xmlns:old="(old-namespace)" xmlns:new="(new namespace)">
<xsl:element name="new:{local-name()">
<xsl:apply-templates select="@*, node()"/>
</xsl:element>
</xsl:template>
答案 1 :(得分:0)
您无法在命名空间URI中使用任何通配符,而使用XSLT 1.0,您无法使用*
作为前缀。
也许starts-with()
就足够了?
示例...
XML输入
<dynamic>
<rpc xmlns="http://namespace/example/123/format" >
<route>
<table>
<tablename>employee</tablename>
<count>20</count>
</table>
<table>
<tablename>employee</tablename>
<count> 21</count>
<rt> 1</rt>
<rt> 2</rt>
<rt> 3</rt>
<rt> 4</rt>
</table>
<table>
<tablename>dept</tablename>
<count>20</count>
<rt> a</rt>
<rt> b</rt>
<rt> c</rt>
</table>
<table>
<tablename>employee</tablename>
<count> 21</count>
<rt> 5</rt>
<rt> 6</rt>
<rt> 7</rt>
<rt> 8</rt>
</table>
<table>
<tablename>dept</tablename>
<count>44</count>
<rt> d</rt>
<rt> e</rt>
<rt> g</rt>
</table>
</route>
</rpc>
</dynamic>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(namespace-uri(),'http://namespace/example')]">
<xsl:element name="{local-name()}" namespace="http://namespace/example">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XML输出
<dynamic>
<rpc xmlns="http://namespace/example">
<route>
<table>
<tablename>employee</tablename>
<count>20</count>
</table>
<table>
<tablename>employee</tablename>
<count> 21</count>
<rt> 1</rt>
<rt> 2</rt>
<rt> 3</rt>
<rt> 4</rt>
</table>
<table>
<tablename>dept</tablename>
<count>20</count>
<rt> a</rt>
<rt> b</rt>
<rt> c</rt>
</table>
<table>
<tablename>employee</tablename>
<count> 21</count>
<rt> 5</rt>
<rt> 6</rt>
<rt> 7</rt>
<rt> 8</rt>
</table>
<table>
<tablename>dept</tablename>
<count>44</count>
<rt> d</rt>
<rt> e</rt>
<rt> g</rt>
</table>
</route>
</rpc>
</dynamic>
像迈克尔凯在他的回答中建议的那样,我分两个阶段做这个转变。第一阶段是这种转换以规范化命名空间。第二个转换将来自my other answer进行分组。
你可能使用local-name()
使我的原始变换更通用,但它很匆忙变得难看,我不推荐它。这是一个例子,你可以做出自己的决定。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="table-by-name" match="*[local-name()='table']" use="*[local-name()='tablename']"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(namespace-uri(),'http://namespace/example')]">
<xsl:element name="{local-name()}" namespace="http://namespace/example">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="*[local-name()='route'][starts-with(namespace-uri(),'http://namespace/example')]"
priority="1">
<xsl:element name="{local-name()}" namespace="http://namespace/example">
<xsl:for-each
select="*[local-name()='table'][count(.|key('table-by-name',*[local-name()='tablename'])[1])=1]">
<xsl:element name="{local-name()}" namespace="http://namespace/example">
<xsl:apply-templates
select="*[local-name()='tablename']|
*[local-name()='count']|
key('table-by-name',*[local-name()='tablename'])/*[local-name()='rt']"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>