我想避免在我的XSLT输出中产生重复的命名空间。
(我正在使用XSLT来按摩一些XML,以便Microsoft的DataContractSerializer认为适合实际处理它.DCS似乎不喜欢的一件事是多次定义相同的命名空间。)
我从XXX元素下获取所有“特征”元素,并将它们组合在一个新的数组元素中,如下所示:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:feature="some namespace">
<xsl:template match="feature:XXX">
<xsl:copy>
<feature:Characteristics>
<xsl:apply-templates select="feature:Characteristics"/>
</feature:Characteristics>
<xsl:copy-of select="*[not(self::feature:Characteristics)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="feature:Characteristics">
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xsl:value-of select="." />
</arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>
“feature”命名空间在XSLT文件的顶部定义。但是,在源XML中不会找到值“feature”,它将是一些任意前缀(通常为“h”)。问题是如果我使用这个XSLT,那么命名空间被分配给输出XML中的2个前缀:来自输入XML的原始命名空间(通常是“h”)和XSLT生成的“特征”。 (虽然有效的XML,但这会让可怜的微软感到困惑。)
所以我想通过改为引用当前元素的命名空间来完全避免在输出XML中定义“feature”命名空间。我试过这个变种,但我不知道如何正确设置xsl:element的命名空间值,以获取当前上下文节点的命名空间前缀......
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:feature="some namespace">
<xsl:template match="feature:XXX">
<xsl:copy>
<xsl:element name="Characteristics" namespace="{???}">
<xsl:apply-templates select="feature:Characteristics"/>
</xsl:element>
<xsl:copy-of select="*[not(self::feature:Characteristics)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="feature:Characteristics">
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xsl:value-of select="." />
</arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>
示例输入:
<h:XXX xmlns:h="http://stackoverflow.com">
<h:Characteristics>7</h:Characteristics>
<h:Characteristics>11</h:Characteristics>
<h:Characteristics>12</h:Characteristics>
<h:ProductName>blah</h:ProductName>
<h:Vendor>blah</h:Vendor>
<h:Version></h:Version>
</h:XXX>
重复名称空间(不好):
<h:XXX xmlns:h="http://stackoverflow.com">
<feature:Characteristic xmlns:feature="http://stackoverflow.com">
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">7</arrays:unsignedShort>
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">11</arrays:unsignedShort>
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">12</arrays:unsignedShort>
</feature:Characteristic>
<h:ProductName>blah</h:ProductName>
<h:Vendor>blah</h:Vendor>
<h:Version></h:Version>
</h:XXX>
期望的输出:
<h:XXX xmlns:h="http://stackoverflow.com">
<h:Characteristic>
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">7</arrays:unsignedShort>
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">11</arrays:unsignedShort>
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">12</arrays:unsignedShort>
</h:Characteristic>
<h:ProductName>blah</h:ProductName>
<h:Vendor>blah</h:Vendor>
<h:Version></h:Version>
</h:XXX>
这个XSLT几乎可以工作,但它涉及硬编码“h”值,我想支持一个任意值:
<?xml version ="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:feature="some ns"
xmlns:h="some ns"
exclude-result-prefixes="h">
<xsl:template match="feature:XXX">
<xsl:copy>
<h:Characteristic>
<xsl:apply-templates select="feature:Characteristics"/>
</h:Characteristic>
<xsl:copy-of select="*[not(self::feature:Characteristics)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="feature:Characteristics">
<arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xsl:value-of select="." />
</arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
我刚删除了feature
名称空间;如果我理解正确,它将包含与h
相同的URI,对吧?
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://stackoverflow.com">
<xsl:output method="xml" indent="yes" />
<xsl:template match="h:XXX" >
<xsl:copy>
<h:Characteristics>
<xsl:apply-templates select="h:Characteristics"/>
</h:Characteristics>
<xsl:copy-of select="*[not(self::h:Characteristics)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="h:Characteristics">
<arrays:unsignedShort
xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xsl:value-of select="." />
</arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这似乎对我有用,我相信必须有一个更简单的方法,但我现在想不到。所有这一切都使用 name()函数来获取根名称的前缀名称, substring-before()以获取前缀然后重建值并发出它们作为未转义的文本。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:feature="http://stackoverflow.com"
exclude-result-prefixes="feature" >
<xsl:template match="feature:XXX">
<xsl:variable name="p" select="substring-before(name(), ':')"/>
<xsl:copy>
<xsl:value-of select="concat('<', $p,':Characteristic', '>')" disable-output-escaping="yes"/>
<xsl:apply-templates select="feature:Characteristics"/>
<xsl:value-of select="concat('</', $p,':Characteristic', '>')" disable-output-escaping="yes"/>
<xsl:copy-of select="*[not(self::feature:Characteristics)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="feature:Characteristics">
<arrays:unsignedShort
xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xsl:value-of select="." />
</arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
如果您需要一致的名称空间前缀,则需要生成新元素,而不是 copy-of 。在XSLT中将名称空间前缀设置为您想要的名称(feature,h等)。
以下XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:feature="http://stackoverflow.com"
xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xsl:output method="xml" indent="yes" />
<xsl:template match="feature:XXX">
<xsl:element name="feature:XXX">
<feature:Characteristic>
<xsl:apply-templates select="feature:Characteristics"/>
</feature:Characteristic>
<xsl:apply-templates select="*[not(self::feature:Characteristics)]" />
</xsl:element>
</xsl:template>
<xsl:template match="feature:Characteristics">
<xsl:element name="arrays:unsignedShort">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:element name="feature:{local-name()}" >
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
生成以下输出:
<?xml version="1.0" encoding="UTF-16"?>
<feature:XXX xmlns:feature="http://stackoverflow.com">
<feature:Characteristic xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<arrays:unsignedShort>7</arrays:unsignedShort>
<arrays:unsignedShort>11</arrays:unsignedShort>
<arrays:unsignedShort>12</arrays:unsignedShort>
</feature:Characteristic>
<feature:ProductName>blah</feature:ProductName>
<feature:Vendor>blah</feature:Vendor>
<feature:Version></feature:Version>
</feature:XXX>