我正在编写一个转换,我希望将xmlns属性(xmlns="myNS"
)添加到根节点。
应用转换时,xmlns
属性包含在某些子元素中。
我无法弄清楚如何将我的转换更改为仅将其应用于根元素。
XML
<db:result xmlns:db="http://www.sonicsw.com/esb/service/dbservice">
<db:resultSet version="1.1">
<db:row>
<id>a</id>
<value1>b</value1>
<value2>c</value2>
</db:row>
<db:row>
<id>a</id>
<value1>d</value1>
<value2>e</value2>
</db:row>
<db:row>
<id>a</id>
<value1>f</value1>
<value2>g</value2>
</db:row>
<db:row>
<id>a</id>
<value1>h</value1>
<value2>i</value2>
</db:row>
</db:resultSet>
</db:result>
XSLT
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:db="http://www.sonicsw.com/esb/service/dbservice"
exclude-result-prefixes="db">
<xsl:template match="/">
<xsl:for-each-group select="//db:row" group-by="id">
<xsl:sort select="id"/>
<xsl:apply-templates select="." mode="document"/>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="db:row" mode="document">
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNS">
<id><xsl:value-of select="id"/></id>
<lines>
<xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/>
</lines>
</root>
</xsl:template>
<xsl:template match="db:row" mode="line">
<line>
<valueof1><xsl:value-of select="value1"/></valueof1>
<valueof2><xsl:value-of select="value2"/></valueof2>
</line>
</xsl:template>
</xsl:stylesheet>
XML输出
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="myNS">
<id>a</id>
<lines>
<line xmlns="">
<valueof1>b</valueof1>
<valueof2>c</valueof2>
</line>
<line xmlns="">
<valueof1>d</valueof1>
<valueof2>e</valueof2>
</line>
<line xmlns="">
<valueof1>f</valueof1>
<valueof2>g</valueof2>
</line>
<line xmlns="">
<valueof1>h</valueof1>
<valueof2>i</valueof2>
</line>
</lines>
</root>
XML预期输出
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="myNS">
<id>a</id>
<lines>
<line>
<valueof1>b</valueof1>
<valueof2>c</valueof2>
</line>
<line>
<valueof1>d</valueof1>
<valueof2>e</valueof2>
</line>
<line>
<valueof1>f</valueof1>
<valueof2>g</valueof2>
</line>
<line>
<valueof1>h</valueof1>
<valueof2>i</valueof2>
</line>
</lines>
</root>
注意:我找到了这个现有帖子,但无法解决如何应用建议的解决方案:
答案 0 :(得分:2)
样式表中的文字结果元素从样式表中的范围内的xmlns
声明中获取其名称空间,即在
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNS">
<id><xsl:value-of select="id"/></id>
<lines>
<xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/>
</lines>
</root>
root
元素及其所有未加前缀的子元素都在myNS
命名空间中。但是在
<xsl:template match="db:row" mode="line">
<line>
<valueof1><xsl:value-of select="value1"/></valueof1>
<valueof2><xsl:value-of select="value2"/></valueof2>
</line>
</xsl:template>
line
和valueofN
元素没有名称空间,因为样式表中此时范围内没有默认xmlns
。
所以简单的答案是将xmlns="myNS"
从root
模板中的db:row
元素移到顶层xsl:stylesheet
而不是:
<xsl:stylesheet version="2.0"
xmlns="myNS"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:db="http://www.sonicsw.com/esb/service/dbservice"
exclude-result-prefixes="db">
<xsl:template match="/">
<xsl:for-each-group select="//db:row" group-by="id">
<xsl:sort select="id"/>
<xsl:apply-templates select="." mode="document"/>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="db:row" mode="document">
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<id><xsl:value-of select="id"/></id>
<lines>
<xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/>
</lines>
</root>
</xsl:template>
<xsl:template match="db:row" mode="line">
<line>
<valueof1><xsl:value-of select="value1"/></valueof1>
<valueof2><xsl:value-of select="value2"/></valueof2>
</line>
</xsl:template>
</xsl:stylesheet>
虽然请注意,如果原始XML中的row
元素不具有相同的ID,则此样式表将不会生成格式正确的输出,因为您将获得多个root
元素单身父母。您可能希望在match="/"
模板中添加包装元素,以确保输出格式正确。
P.S。由于您使用的是for-each-group
,因此丢失mode="document"
模板并将其内容直接移到feg中可能会更有效,然后使用current-group
而不必过滤{{1} }}:
[id=current()/id]