我正在编写第一个转换XML文件的XSLT代码。
下面的示例代码只是为了解释这里的问题。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn.abc.xyz" xmlns:ns2="abc:cde">
<xsl:template match="/catalog">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>Price</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
当所有名称空间在输入XML中都有前缀时,上面的代码工作得很好。但是当XML中缺少命名空间前缀时,即执行只显示没有标记名称的XML内容,则无法工作。
输入XML
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn.abc.xyz" xmlns:ns2="abc:cde">
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
以上XML的输出:标题艺人价格
与前缀:
<catalog xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:abc="urn.abc.xyz" xmlns:ns2="abc:cde">
没有前缀
<catalog xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn.abc.xyz" xmlns:ns2="abc:cde">
如果我运行没有名称空间前缀(abc)的XSL然后输出如下所示
帝国滑剧鲍勃·迪伦美国哥伦比亚10.90 1985
谁能帮助为什么我的XSL不工作时,名称空间前缀是空的?在我的XSL中需要做哪些更改,以便即使缺少名称空间前缀也能正常工作。
不带前缀的命名空间声明定义了一个默认命名空间,并将所有未带前缀的元素置于该命名空间的声明范围内。
为了在样式表中处理这些元素,必须声明相同的名称空间,为其分配一个前缀,并将该前缀用于源XML中的所有无前缀元素。
例如,如果输入的XML是:
<catalog xmlns="urn.abc.xyz">
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
那么你的样式表需要是:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:abc="urn.abc.xyz"
exclude-result-prefixes="abc">
<xsl:template match="/abc:catalog">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>Price</th>
</tr>
<xsl:for-each select="abc:cd">
<tr>
<td><xsl:value-of select="abc:title"/></td>
<td><xsl:value-of select="abc:artist"/></td>
<td><xsl:value-of select="abc:price"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
(你可以使用任何你想要的前缀)
但是,这个样式表不适合处理元素为no-namespace的输入:
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
从技术上讲,可以构造一个样式表,忽略名称空间,只使用元素的本地名称来处理这两个xml。但是,除非绝对必要,否则不建议这样做。假设名称空间的存在是有原因的,忽略它们可能会导致不正确的结果。
还请注意,使用前缀的名称空间声明,例如示例中的xmlns:ns2="abc:cde"
,仅应用于具有相同前缀的节点。如果没有这样的节点,这样的声明就没有效果,而且是完全多余的(与你的问题无关)。
在XSLT 1.0中,如果源文档中的元素位于名称空间中,则必须在XSLT中的XPath表达式中使用名称空间前缀。
在源文档中声明" run .abc.xyz"作为默认名称空间URI。(顺便说一句,"urn.abc.xyz"不是真正合适的名称空间URI;它应该是一个绝对URI,包括一个URI方案,例如:urn:abc.xyz;或者别的什么,但这不是你的问题)。
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn.abc.xyz">
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
(注:我删除了未使用的XSLT和"ns2"命名空间声明(因为它们没有在文件的任何地方使用)。
在XSLT中,您有一个XPath匹配表达式=/catalog
的模板,但是因为catalog
没有名称空间前缀,所以它只匹配没有名称空间中的catalog
元素。要匹配urn.abc.xyz
名称空间中的catalog
元素,您需要首先将名称空间前缀(可以是任何东西,例如my-namespace
)与urn.abc.xyz
名称空间URI相关联,然后使用XPath表达式"/my-namespace:catalog"在模板的match属性中。要将urn.abc.xyz
名称空间URI绑定到前缀my-namespace
,请向样式表元素添加名称空间声明:xmlns:my-namespace="urn.abc.xyz"
然后在模板中,您的xsl:for-each
语句将使用表达式my-namespace:cd
引用子元素,类似地,您需要使用my-namespace:title
等来引用cd
元素的子元素。