我试图了解是否可以使用具有类似但不等于模式的xml文件重用XSLT 1.0 脚本,这些模式共享相同的命名空间前缀。
变量ns-uri
包含所需的命名空间,但似乎XSLT 1.0无法识别xmlns:emp='$ns-uri'
中的这种用法,尽管使用带有命名空间的字符串的相同属性也可以。
我不想遵循使用构造*[name()='emp:department']
的建议,因为这会使xslt完全不可读。
还有更多建议或者这是对XSLT 1.0的最终限制吗?
注意:由于我使用的是前缀,How to automatically propagate the XMLNS attribute from on XSL template to another中的答案不适用。
谢谢。
以下不有效:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="ns-uri" select="/child::*[1]/namespace-uri()"/>
<xsl:template match="emp:employee" xmlns:emp="http://www.example.com/ns/employee/2006">
First Name "<xsl:value-of select="emp:first" xmlns:emp="http://www.example.com/ns/employee/2006"/>"
Last Name "<xsl:value-of select="emp:last" xmlns:emp='$ns-uri'/>"
Department "<xsl:value-of select="*[name()='emp:department']"/>"
</xsl:template>
</xsl:stylesheet>
我正在使用这些xml文件作为示例(来自Finnbarr P. Murphy's "XSLT 1.0 Multiple Namespace Issues"中的示例)
sample1.xml :
<?xml version="1.0"?>
<emp:root xmlns:emp="http://www.example.com/ns/employee/2006">
<emp:employee status="Guru">
<emp:first>John</emp:first>
<emp:last>Kane</emp:last>
<emp:department>IT</emp:department>
<emp:country>IE</emp:country>
</emp:employee>
</emp:root>
sample2.xml :
<?xml version="1.0"?>
<emp:root xmlns:emp="http://www.example.com/ns/employee/2012">
<emp:employee status="Guru">
<emp:first>John</emp:first>
<emp:last>Kane</emp:last>
<emp:department>IT</emp:department>
<emp:country>IE</emp:country>
</emp:employee>
</emp:root>
在两种情况下都应该得到理想的结果:
First Name "John"
Last Name "Kane"
Department "IT"
答案 0 :(得分:1)
您见证的问题是由不同的命名空间引起的:
emp
命名空间定义为"xmlns:emp="http://www.example.com/ns/employee/2006"
emp
命名空间定义为"xmlns:emp="http://www.example.com/ns/employee/2012"
因此,在一种情况下,您的模板会失败,因为<template...>
的规则由于不同的名称空间前缀(...2006
!= {而不匹配{1}})。
因此,要创建一个忽略命名空间的模板,必须忽略 namespace-prefixes 。
这是通过仅考虑元素名称的...2012
而不是全名来完成的。
例如,名称空间元素的名称可能是local-name()
因此emp:first
会返回name()
而emp:first
只返回local-name()
。
忽略名称空间前缀(在本例中为first
)是通过仅关注所有相关元素的emp
来实现的。
因此,以下模板由
构建local-name()
*
限制这组元素,该谓词检查[local-name() = '...']
匹配的元素整个模板看起来像这样
local-name()
并为两个XML输入文件返回相同的结果。
答案 1 :(得分:0)
不,您不能将前缀绑定到变量URI。
然而,前缀本身并不重要 - 只有URI很重要。如果您知道预期的命名空间URI是什么,您可以将它们中的每一个绑定到它自己的前缀并使用它们,例如:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:emp6="http://www.example.com/ns/employee/2006"
xmlns:emp12="http://www.example.com/ns/employee/2012">
<xsl:output method="text"/>
<xsl:template match="emp6:employee | emp12:employee">
First Name "<xsl:value-of select="emp6:first | emp12:first"/>"
Last Name "<xsl:value-of select="emp6:last | emp12:last" />"
Department "<xsl:value-of select="emp6:department | emp12:department"/>"
</xsl:template>
</xsl:stylesheet>
另一种选择是首先从传入的XML中获取名称空间URI(就像你开始做的那样)并使用它来生成一个XSLT样式表,其中(常量)前缀绑定到提取的URI。
然后将生成的样式表应用于原始XML,以获得最终结果。