如何在XSLT的for-each处理中为values子元素添加指定命名空间?
如何给XSLT处理后的values子元素添加指定命名空间?
你现在的需求是把values节点下的所有子元素都加上ns前缀的命名空间,对吧?你的现有XSLT已经实现了把data下的label节点去掉、只保留values内容的效果,接下来只需要修改对values子元素的处理逻辑,给它们添加上命名空间即可。
解决方案:使用模板匹配修改元素命名空间
最符合XSLT设计思想的方式是新增一个专门处理values子元素的模板,通过<xsl:element>来创建带指定命名空间的元素。修改后的完整XSLT如下:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://example.com/ns"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <!-- Identity模板:默认复制所有未被特殊模板匹配的节点 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- 处理data节点:只保留values下的子元素 --> <xsl:template match="data"> <data> <xsl:apply-templates select="values/*" /> </data> </xsl:template> <!-- 给values下的所有子元素添加ns命名空间 --> <xsl:template match="values/*"> <!-- 创建带命名空间的元素:前缀ns + 原元素本地名称 --> <xsl:element name="ns:{local-name()}" namespace="http://example.com/ns"> <!-- 复制原元素的属性和内容 --> <xsl:apply-templates select="@*|node()" /> </xsl:element> </xsl:template> </xsl:stylesheet>
代码解释
- Identity模板:保留原有的默认复制逻辑,确保
products、data这些不需要修改的节点能被正常复制。 - data节点模板:直接选择
values下的所有子元素(values/*)来应用模板,替代了你原来的for-each写法,更简洁也更符合XSLT的模板匹配模式。 - values子元素模板:
- 使用
<xsl:element>动态创建元素,name="ns:{local-name()}"会把原元素的本地名称(比如a、b)加上ns前缀; namespace属性指定了命名空间的URI,必须和stylesheet开头声明的ns前缀对应的URI完全一致;- 最后复制原元素的属性和内部内容(这里原元素只有文本节点,所以会保留原来的文本值)。
- 使用
如果你坚持使用for-each的写法
如果不想修改模板匹配逻辑,也可以在你原来的for-each循环里直接创建带命名空间的元素,修改后的data模板如下:
<xsl:template match="data"> <data> <xsl:variable name="values" select="values" /> <xsl:for-each select="$values/*"> <xsl:element name="ns:{local-name()}" namespace="http://example.com/ns"> <xsl:apply-templates select="@*|node()" /> </xsl:element> </xsl:for-each> </data> </xsl:template>
最终输出效果
运行修改后的XSLT,你会得到符合需求的输出:
<products> <data> <ns:a>a</ns:a> <ns:b>b</ns:b> </data> <data> <ns:c>c</ns:c> <ns:d>d</ns:d> </data> </products>
内容的提问来源于stack exchange,提问作者Tomas
相关产品推荐
相关产品推荐

