我试图了解 XSLT 是否可行 1.0 脚本可与具有相似但不相等模式的 xml 文件重用,这些模式共享相同的命名空间前缀。
变量 ns-uri
包含所需的 namespace ,但 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" 中的示例)
样本1.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>
样本2.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"
最佳答案
您目睹的问题是由不同的命名空间引起的:
emp
命名空间为 "xmlns:emp="http://www.example.com/ns/employee/2006"
emp
命名空间为 "xmlns:emp="http://www.example.com/ns/employee/2012"
所以在一种情况下你的模板会失败,因为它的
<template...>
由于不同的命名空间前缀 ( ...2006
!= ...2012
),s 规则将不匹配。因此,要创建忽略 namespace 的模板,必须忽略 namespace 前缀。
这仅通过关于
local-name()
来完成元素的名称而不是整个名称。例如,命名空间元素的名称可能是
emp:first
.所以
name()
会返回 emp:first
和 local-name()
只会返回 first
.忽略命名空间前缀(在本例中为
emp
)是通过只关注 local-name()
来实现的。所有相关元素。所以下面的模板是由
*
选择所有元素[local-name() = '...']
来限制这组元素它检查 local-name()
的元素匹配 整个模板看起来像这样
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="*[local-name() = 'employee']">
First Name "<xsl:value-of select="*[local-name() = 'first']" />"
Last Name "<xsl:value-of select="*[local-name() = 'last']" />
Department "<xsl:value-of select="*[local-name() = 'department']" />"
</xsl:template>
</xsl:stylesheet>
并为两个 XML 输入文件返回相同的结果。
关于xml - XSLT 1.0 可以在 select 子句中的 xmlns 属性上使用变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42860885/