将嵌套的xml节点与xslt结合使用

时间:2013-11-26 00:04:25

标签: xml xslt xslt-2.0 xpath-2.0

我正在尝试梳理以下两个文件:

ls -lR test

test:
total 8
-rw-r--r-- 1 xxx002 users 212 2013-11-25 17:36 file1.xml
-rw-r--r-- 1 xxx002 users 212 2013-11-25 17:36 file2.xml

cat test / file1.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<Config>
   <HostGroup Name="X">
      <Host Name="A"/>
   </HostGroup>
   <HostGroup Name="Y">
      <Host Name="A"/>
      <Host Name="B"/>
   </HostGroup>
</Config>

cat test / file2.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<Config>
   <HostGroup Name="X">
      <Host Name="B"/>
   </HostGroup>
   <HostGroup Name="Z">
      <Host Name="A"/>
      <Host Name="B"/>
   </HostGroup>
</Config>

进入以下输出:

<?xml version="1.0" encoding="ISO-8859-1"?>
<HostGroup Name="X">
   <Host Name="A"/>
   <Host Name="B"/>
</HostGroup>
<HostGroup Name="Y">
   <Host Name="A"/>
   <Host Name="B"/>
</HostGroup>
<HostGroup Name="Z">
   <Host Name="A"/>
   <Host Name="B"/>
</HostGroup>

到目前为止,我有以下xslt:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/>

<xsl:variable name="collection">
        <xsl:copy-of select="collection('file:/home/xxx002/xslt/test/?select=*.xml;strip-space=yes;recurse=yes')/*"/>
</xsl:variable>

<xsl:variable name="HostGps" select="$collection/Config/HostGroup"/>

<xsl:template name="foo" match="/*">
        <xsl:for-each-group select="$HostGps" group-by="@Name">
                <xsl:sort select="current-grouping-key()"/>
                <xsl:if test="not(./@Name = preceding-sibling::Property/@Name)">
                        <HostGroup>
                        <xsl:attribute name="Name">
                                <xsl:value-of select="current-grouping-key()"/>
                        </xsl:attribute>
                        <xsl:variable name="Hosts">
                                <xsl:perform-sort select="./Host">
                                        <xsl:sort select="@Name"/>
                                </xsl:perform-sort>
                        </xsl:variable>
                        <xsl:copy-of select="$Hosts"/>
                        </HostGroup>
                </xsl:if>
        </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

输出不太正确。它只在HostGroup X的第一个实例中获取Host A.任何人都可以帮我解决这个问题吗?

谢谢, 布赖恩

1 个答案:

答案 0 :(得分:0)

看起来您只需要更改select上的xsl:perform-sort属性。

这个XSLT 2.0 ......

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs">

    <xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/>

    <xsl:variable name="collection">
        <xsl:copy-of select="collection('file:///C:/Users/dhaley/Desktop/so_test/?select=*.xml;strip-space=yes;recurse=yes')/*"/>
    </xsl:variable>

    <xsl:variable name="HostGps" select="$collection/Config/HostGroup"/>

    <xsl:template name="foo" match="/*">
        <xsl:for-each-group select="$HostGps" group-by="@Name">
            <xsl:sort select="current-grouping-key()"/>
            <xsl:if test="not(./@Name = preceding-sibling::Property/@Name)">
                <HostGroup Name="{current-grouping-key()}">
                    <xsl:variable name="Hosts">
                        <xsl:perform-sort select="current-group()/*">
                            <xsl:sort select="@Name"/>
                        </xsl:perform-sort>
                    </xsl:variable>
                    <xsl:copy-of select="$Hosts"/>
                </HostGroup>
            </xsl:if>
        </xsl:for-each-group>
    </xsl:template>

</xsl:stylesheet>

...可生产

<HostGroup Name="X">
   <Host Name="A"/>
   <Host Name="B"/>
</HostGroup>
<HostGroup Name="Y">
   <Host Name="A"/>
   <Host Name="B"/>
</HostGroup>
<HostGroup Name="Z">
   <Host Name="A"/>
   <Host Name="B"/>
</HostGroup>

注意:我还将xsl:attribute替换为AVT并添加了exclude-result-prefixes。这些并非绝对必要。