我有大量的XML文件,我需要使用XSLT进行转换。问题是许多这些文件是由不同的人手写的,他们不使用一致的名称来引用模式。例如,一个文件可能使用:
xmlns:itemType="http://example.com/ItemType/XSD"
其他人可能会使用前缀“it”而不是“itemType”:
xmlns:it="http://example.com/ItemType/XSD"
如果这还不够糟糕,有几个文件使用两个或三个同义词来做同样的事情!
<?xml version="1.0"?> <Document xmlns:it="http://example.com/ItemType/XSD" xmlns:itemType="http://example.com/ItemType/XSD" xmlns:ItemType="http://example.com/ItemType/XSD" ...
(显然有很多切割和粘贴)
现在,因为XSLT文件中的模式匹配似乎对命名空间前缀有效(与它所涉及的模式相反),所以模式只匹配其中一个变体。所以,如果我写的话:
<xsl:template match="SomeNode[@xsi:type='itemType:SomeType']"> ... </xsl:template>
然后它只匹配我想要它的一部分案例。
问题1:有没有办法让XSLT匹配所有变种?
问题2:有没有办法删除重复项,以便所有输出文件都使用一致的命名?
我天真地尝试使用“命名空间别名”,但我想我误解了它的作用,因为我根本无法做任何事情 - 要么匹配所有变体,要么影响输出XML。
<?xsl:stylesheet version="1.0" ... xmlns:it="http://example.com/ItemType/XSD" xmlns:itemType="http://example.com/ItemType/XSD" xmlns:ItemType="http://example.com/ItemType/XSD" ... <xsl:output method="xml" indent="yes"/> <xsl:namespace-alias stylesheet-prefix="it" result-prefix="ItemType"/> <xsl:namespace-alias stylesheet-prefix="itemType" result-prefix="ItemType"/>
答案 0 :(得分:1)
除非您明确说明,否则属性值或文本节点不会强制转换为QName。虽然这只适用于XSLT / XPath 2.0
在XSLT / XPath 1.0中,您必须“手动”执行此操作:
<xsl:template match="SomeNode">
<xsl:variable name="vPrefix" select="substring-before(@xsi:type,':')"/>
<xsl:variable name="vNCName"
select="translate(substring-after(@xsi:type,$vPrefix),':','')"/>
<xsl:if test="namespace::*[
name()=$vPrefix
] = 'http://example.com/ItemType/XSD'
and
$vNCName = 'SomeType'">
<!-- Content Template -->
<xsl:if>
</xsl:template>
编辑:一体化模式(可读性较差):
<xsl:template match="SomeNode[
namespace::*[
name()=substring-before(../@xsi:type,':')
] = 'http://example.com/ItemType/XSD'
and
substring(
concat(':',@xsi:type),
string-length(@xsi:type) - 7
) = ':SomeType'
]">
<!-- Content Template -->
</xsl:template>
答案 1 :(得分:1)
在XSLT 2.0中(无论您是否使用模式感知),您可以将谓词编写为[@xsi:type=xs:QName('it:SomeType')]
,其中“it”是在此命名空间的样式表中声明的前缀。它不必与源文档中使用的前缀相同。
当然,元素和属性名称的匹配(与QName值内容不同)在XSLT 1.0和XSLT 2.0中使用名称空间URI而不是前缀。