4

我有三个xml文件

<step>
<Products>
    <Product UserTypeID="Country">
        <Name>Cyprus</Name>
        <Product UserTypeID="Resort">
            <Name>Argaka</Name>
            <Product UserTypeID="Property">
                <Name>Villa Tester</Name>
            </Product>
        </Product>
        <Product UserTypeID="Resort">
            <Name>Coral Bay</Name>
            <Product UserTypeID="Property">
                <Name>1</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>2</Name>
            </Product>
        </Product>
    </Product>
    <Product UserTypeID="Country">
        <Name>Greece</Name>
        <Product UserTypeID="Region">
            <Name>Corfu</Name>
            <Product UserTypeID="Resort">
                <Name>Aghios Stefanos</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Joanna</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa Eleonas</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Kassiopi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa 2</Name>
                </Product>
            </Product>
        </Product>
    </Product>
</Products>

<step>
<Products>
    <Product UserTypeID="Country">
        <Name>Cyprus</Name>
        <Product UserTypeID="Resort">
            <Name>Argaka</Name>
            <Product UserTypeID="Property">
                <Name>Villa Jaime</Name>
            </Product>
        </Product>
    </Product>
    <Product UserTypeID="Country">
        <Name>Greece</Name>
        <Product UserTypeID="Region">
            <Name>Corfu</Name>
            <Product UserTypeID="Resort">
                <Name>Acharavi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa 1</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa 2</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Gouvia</Name>
                <Product UserTypeID="Property">
                    <Name>Villa De Bono</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Kassiopi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa 1</Name>
                </Product>
            </Product>
        </Product>
    </Product>
</Products>

<step>
<Products>
    <Product UserTypeID="Country">
        <Name>Cyprus</Name>
        <Product UserTypeID="Resort">
            <Name>Aghia Marina</Name>
            <Product UserTypeID="Property">
                <Name>Villa Aghia Marina</Name>
            </Product>
        </Product>
        <Product UserTypeID="Resort">
            <Name>Coral Bay</Name>
            <Product UserTypeID="Property">
                <Name>Ascos Coral Villas</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>Coral Villa</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>Lella Villas</Name>
            </Product>
        </Product>
    </Product>
    <Product UserTypeID="Country">
        <Name>Greece</Name>
        <Product UserTypeID="Region">
            <Name>Corfu</Name>
            <Product UserTypeID="Resort">
                <Name>Acharavi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Angelos</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa Eleonas</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Aghios Stefanos</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Joanna</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa Eleonas</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Kassiopi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Imerolia</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Test Property</Name>
                </Product>
            </Product>
        </Product>
    </Product>
</Products>

每个文件都有相同的产品(按./name),但有不同的子产品(按./name),我需要将它们连接成一棵树,每个产品/名称一个产品,包含相同规则的所有子产品,以便我可以输出一种结构。

我找到了一个 xslt 方法,它将创建一个节点集,如下所示

    <xsl:variable name="step-output">
    <xsl:for-each select="/index/file">
        <xsl:copy-of select="document(.)" />
    </xsl:for-each>
</xsl:variable>
<xsl:variable name="step-products" select="exsl:node-set($step-output)//Products" />

但是,当我创建其他模板时,将按产品/名称创建三个产品,即塞浦路斯将出现三次。

有谁知道我要怎么做??我的结果需要如下

<step>
<Products>
    <Product UserTypeID="Country">
        <Name>Cyprus</Name>
        <Product UserTypeID="Resort">
            <Name>Aghia Marina</Name>
            <Product UserTypeID="Property">
                <Name>Villa Aghia Marina</Name>
            </Product>
        </Product>
        <Product UserTypeID="Resort">
            <Name>Argaka</Name>
            <Product UserTypeID="Property">
                <Name>Villa Jaime</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>Villa Tester</Name>
            </Product>
        </Product>
        <Product UserTypeID="Resort">
            <Name>Coral Bay</Name>
            <Product UserTypeID="Property">
                <Name>Ascos Coral Villas</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>Coral Villa</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>Lella Villas</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>1</Name>
            </Product>
            <Product UserTypeID="Property">
                <Name>2</Name>
            </Product>
        </Product>
    </Product>
    <Product UserTypeID="Country">
        <Name>Greece</Name>
        <Product UserTypeID="Region">
            <Name>Corfu</Name>
            <Product UserTypeID="Resort">
                <Name>Acharavi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Angelos</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa Eleonas</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa 1</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa 2</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Aghios Stefanos</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Joanna</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa Eleonas</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Gouvia</Name>
                <Product UserTypeID="Property">
                    <Name>Villa De Bono</Name>
                </Product>
            </Product>
            <Product UserTypeID="Resort">
                <Name>Kassiopi</Name>
                <Product UserTypeID="Property">
                    <Name>Villa Imerolia</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Test Property</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa 1</Name>
                </Product>
                <Product UserTypeID="Property">
                    <Name>Villa 2</Name>
                </Product>
            </Product>
        </Product>
    </Product>
</Products>

4

2 回答 2

4

这是一个应该可以完成这项工作的 XSLT 2.0 样式表:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <step>
      <Products>
        <xsl:for-each-group select="document(index/file)/step/Products/Product" group-by="Name">
          <Product UserTypeID="{@UserTypeID}">
            <Name><xsl:value-of select="current-grouping-key()"/></Name>
            <xsl:for-each-group select="current-group()/Product" group-by="Name">
              <xsl:sort select="current-grouping-key()"/>
              <Product UserTypeID="{@UserTypeID}">
                <Name><xsl:value-of select="current-grouping-key()"/></Name>
                <xsl:for-each select="current-group()/Product">
                  <xsl:sort select="Name"/>
                  <xsl:copy-of select="."/>
                </xsl:for-each>
              </Product>
            </xsl:for-each-group>
          </Product>
        </xsl:for-each-group>
      </Products>
    </step>
  </xsl:template>

</xsl:stylesheet>

您需要针对具有以下结构的索引 XML 文档运行它

<index>
  <file>test2010020803.xml</file>
  <file>test2010020804.xml</file>
  <file>test2010020805.xml</file>
</index>

列出您要处理的其他文件。

XSLT 2.0 样式表可以使用带有.NET 和 Java 版本的Saxon 9执行,因此它可以在至少有 Java 1.5 或 .NET 2.0 可用或可以安装的任何地方运行。其他选项是AltovaXML 工具(仅限 Windows)和Gestalt

如果您与 XSLT 1.0 相关联,那么只要您有 exsl:node-set 或类似的支持,您就可以按以下方式进行操作:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="exsl"
  version="1.0">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="k1" match="step/Products/Product" use="Name"/>
  <xsl:key name="k2" match="step/Products/Product/Product" use="concat(../Name, '|', Name)"/>

  <xsl:template match="/">
    <xsl:variable name="rtf">
      <xsl:copy-of select="document(index/file)/*"/>
    </xsl:variable>
    <step>
      <Products>
        <xsl:for-each select="exsl:node-set($rtf)/step/Products/Product[generate-id() = generate-id(key('k1', Name)[1])]">
          <Product UserTypeID="{@UserTypeID}">
            <xsl:copy-of select="Name"/>
            <xsl:for-each select="key('k1', Name)/Product[generate-id() = generate-id(key('k2', concat(../Name, '|', Name))[1])]">
              <xsl:sort select="Name"/>
              <Product UserTypeID="{@UserTypeID}">
                <xsl:copy-of select="Name"/>
                <xsl:for-each select="key('k2', concat(../Name, '|', Name))/Product">
                  <xsl:sort select="Name"/>
                  <xsl:copy-of select="."/>
                </xsl:for-each>
              </Product>
            </xsl:for-each>
          </Product>
        </xsl:for-each>
      </Products>
    </step>
  </xsl:template>

</xsl:stylesheet>

键如下所示:

  <xsl:key name="k1" match="step/Products/Product" use="Name"/>

  <xsl:key name="k2" match="step/Products/Product/Product" use="concat(../Name, '|', Name)"/>

  <xsl:key name="k3" match="step/Products/Product/Product/Product"
                     use="concat(../../Name, '|', ../Name, '|', Name)"/>

  <xsl:key name="k4" 
           match="step/Products/Product/Product/Product/Product"
           use="concat(../../../Name, '|', ../../Name, '|', ../Name, '|', Name)"/>

  <xsl:key name="k5" 
           match="step/Products/Product/Product/Product/Product/Product"
           use="concat(../../../../Name, '|', ../../../Name, '|', ../../Name, '|', ../Name, '|', Name)"/>

  <xsl:key name="k6" 
           match="step/Products/Product/Product/Product/Product/Product/Product"
           use="concat(../../../../../Name, '|', ../../../../Name, '|', ../../../Name, '|', ../../Name, '|', ../Name, '|', Name)"/>

这都是直接在论坛编辑器中输入的,所以可能有错误。

于 2010-02-08T15:31:13.437 回答
0

编辑文本以创建文件将起作用,但可能难以维护。

最简单的方法是将所有 3 个文件的 XML 解析为对象形式。以编程方式在单个父节点下添加对象,然后重新生成新的 XML 文件。

您的环境是否使其成为可接受的解决方案?

于 2010-02-08T15:15:32.577 回答