使用xslt组合嵌套的xml节点

问题描述 投票:1回答:1

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

ls -lR测试

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

猫测试/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>

猫测试/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的第一个实例中选择主机A。任何人都可以帮助我解决这个问题吗?

谢谢,布莱恩

xml xslt xslt-2.0 xpath-2.0
1个回答
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。这些不是绝对必要的。

© www.soinside.com 2019 - 2024. All rights reserved.