XSLT:使用父节点的命名空间
-
18-09-2019 - |
题
我想避免在我的XSLT输出端产生一个重复的命名空间。
(我使用XSLT来按摩一些XML使微软的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>
在“特征”命名空间是在XSLT文件的顶部限定。然而,值“功能”是不会在源XML被发现,这将是一些任意前缀(通常为“H”)。的问题是,如果使用此XSLT则namespace被分配给2个前缀在输出XML:原命名空间从输入XML(通常为“H”)和由XSLT生成的“特征”。 (虽然有效的XML,该混淆差微软。)
所以想完全避免由代替参考所述当前元素的命名空间而不是定义在输出XML的“特征”的命名空间。我想在这个变种,但我不知道如何设置了xsl的命名空间值:元素正确,以获得当前上下文节点的命名空间前缀...
<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>
解决方案
如果您想一致的命名空间前缀,那么你将需要生成新的元素,而不是复制的。您的命名空间前缀设置为你希望它是什么在XSLT(功能,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>
其他提示
我只是删除该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>
这似乎为我工作,我相信必须有一个更简单的方法,但我不认为在这一刻。所有这一切它使用的名称()的函数来获取根名称的前缀名的子 - 前()的获得则前缀重建的值,并发出他们作为转义文本。
<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>
不隶属于 StackOverflow