【问题标题】:combine nested xml nodes with xslt将嵌套的 xml 节点与 xslt 结合起来
【发布时间】:2013-11-26 00:04:24
【问题描述】:

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

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】:

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

    这个 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。这些不是绝对必要的。

    【讨论】:

    • 谢谢!我刚刚进入这样的变换,我是如此接近......但本可以花几天时间找到它!另外,感谢额外的清理工作(摆脱 xs 并优化 HostGroup Name 元素)。
    • @user3034392 - 你很亲密。不错的作品。我很高兴看到有人使用 XSLT 2.0。似乎 99% 的 XSLT 问题只是 1.0。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    相关资源
    最近更新 更多