2015-01-15 86 views
1

如何在XSLT中动态生成名称空间XML属性?例如,我们可以使用不同的属性,如attr1:fooattr2:bar有下面的XML文档:如何在XSLT中动态生成名称空间XML属性?

<a xmlns="http://example.com/" 
    xmlns:attr1="http://example.com/attr1#" 
    xmlns:attr2="http://example.com/attr2#"> 
    <b attr1:foo=""/> 
    <b attr2:bar=""/> 
</a> 

假设我们要转换文档和更改所有属性的值...。我们应该如何构建这些属性?一个自然的选择如何去做这个将是使用<xsl:attribute>。但是我们应该使用什么QName作为它的name属性?函数name()可以将该属性的QName作为字符串返回。朴素XSL模板可能是这样的:

<xsl:template match="@*"> 
    <xsl:attribute name="{name()}">...</xsl:attribute> 
</xsl:template> 

然而,由于name()返回QName字符串,这种解决方案需要已经通过xmlns在XSLT中预定义的命名空间前缀绑定(例如,xmlns:attr1="http://example.com/attr1#")。

然后我在想,如果使用的<xsl:attribute>namespace属性是要走的路:

<xsl:template match="@*"> 
    <xsl:attribute name="{local-name()}" 
       namespace="{namespace-uri()}">...</xsl:attribute> 
</xsl:template> 

该解决方案似乎工作,但我认为这是很难在XSLT的最佳实践。你知道更好的解决方案吗?

回答

2

这要看你怎么知道的源文档的结构信息:

  • 如果你知道使用的命名空间和它们的前缀绑定,然后 宣布他们在您的样式表,并使用你称为“天真XSL 模板“。

  • 否则复制命名空间(URI),如第二个模板中所示。


还要注意的是,你可以将二者结合起来,如下所示:

<xsl:template match="@*"> 
    <xsl:attribute name="{name()}" namespace="{namespace-uri()}">...</xsl:attribute> 
</xsl:template> 

对于某些处理器(例如撒克逊6.5),这将确保原始前缀在结果中重复使用;其他处理器(例如libxslt和Xalan)也会这样做。

+0

我不知道命名空间前缀绑定事先。这就是为什么我想动态创建名称空间属性的原因。 – 2015-01-15 16:56:58

+0

然后我不知道比你的第二个模板更好的解决方案。你为什么认为这不是最佳做法? – 2015-01-15 16:59:31

+0

好的,我只是不确定它是否是惯用的XSLT。我认为有一个更简单的方法来做到这一点。 – 2015-01-15 17:49:08