1

我正在编写一个转换,我想将 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>

注意:我找到了这个现有的帖子,但无法锻炼如何应用建议的解决方案:

4

1 回答 1

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值。valueofNxmlns

所以简单的答案是将模板中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>

但请注意,如果row原始 XML 中的元素并非都具有相同的 id,则此样式表将不会产生格式正确的输出,因为您将获得多个root没有单个父元素的元素。您可能希望在match="/"模板中添加一个包装元素以确保输出格式正确。

PS,因为你在一个for-each-group它可能会更有效地丢失mode="document"模板并将其内容直接移动到 feg 中,然后使用current-group而不是过滤[id=current()/id]

    <xsl:template match="/">
        <xsl:for-each-group select="//db:row" group-by="id">
            <xsl:sort select="current-grouping-key()"/>
            <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <id><xsl:value-of select="current-grouping-key()"/></id>
                <lines>
                   <xsl:apply-templates select="current-group()" mode="line"/>
                </lines>
            </root>        
        </xsl:for-each-group>
    </xsl:template>
于 2013-03-13T13:27:01.633 回答