0

我有两个 XML 文件并希望合并,合并的标准如下:

nodes1.xml 文件内容:

<nodes>
  <node>
    <type>a</type>
    <name>joe</name>
  </node>
  <node>
    <type>b</type>
    <name>sam</name>
  </node>
  <node>
    <type>c</type>
    <name>pez</name>
  </node>
  <node>
    <type>g</type>
    <name>lua</name>
  </node>
  <node>
    <type>a</type>
    <name>tol</name>
  </node>
  <node>
    <type>c</type>
    <name>jua</name>
  </node>
</nodes>

nodes2.xml 文件内容:

<nodes>
  <node>
    <type>a</type>
    <name>jill</name>
  </node>
  <node>
    <type>c</type>
    <name>imol</name>
  </node>
  <node>
    <type>h</type>
    <name>teli</name>
  </node>
  <node>
    <type>f</type>
    <name>jopp</name>
  </node>
  <node>
    <type>c</type>
    <name>zolh</name>
  </node>
</nodes>

通过我的 xsl 模板,我得到:

<?xml version="1.0" encoding="UTF-8"?>
<nodes>
  <node tipo="a">
    <name>joe</name>
    <name>tol</name>
    <name>jill</name>
  </node>
  <node tipo="c">
    <name>pez</name>
    <name>jua</name>
    <name>imol</name>
    <name>zolh</name>
  </node>
  <node tipo="h">
    <name>teli</name>
  </node>
  <node tipo="f">
    <name>jopp</name>
  </node>
</nodes>

我需要一个解决方案来获得更好的性能。我目前的解决方案是:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name="Source2" select="document('nodes2.xml')/nodes/node"/>
  <xsl:variable name="Source1" select="document('nodes1.xml')/nodes/node"/>
  <xsl:template match="/nodes" >
    <nodes>
      <xsl:for-each-group select="node" group-by="type">
        <node tipo="{type}">
          <xsl:apply-templates select="$Source1[type=current-grouping-key()]/name"/>
          <xsl:apply-templates select="$Source2[type=current-grouping-key()]/name"/>
        </node>
      </xsl:for-each-group>
    </nodes>
  </xsl:template>

  <xsl:template match="name">
    <name><xsl:value-of select="."/></name>
  </xsl:template>
</xsl:stylesheet>

我用 java saxon 运行它:

$ java net.sf.saxon.Transform nodes2.xml mysolution.xsl

我认为将输入文件同时放在一个变量中是“一种耻辱”,但我想不出有什么不同的做法。

我感谢帮助或指针。

——保利诺

4

1 回答 1

0

假设您将第二个文件作为 XSLT 代码的主要输入,您可以使用以下内容:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:param name="source1-uri" select="'nodes1.xml'"/>
  <xsl:variable name="doc1" select="doc($source1-uri)"/>

  <xsl:key name="by-type" match="nodes/node" use="type"/>

  <xsl:template match="/nodes" >
    <nodes>
      <xsl:for-each-group select="key('by-type', node/type, $doc1), node" group-by="type">
        <node tipo="{current-grouping-key()}">
          <xsl:copy-of select="for $n in current-group() return $n/name"/>
        </node>
      </xsl:for-each-group>
    </nodes>
  </xsl:template>

</xsl:stylesheet>

我不确定合并name元素的顺序是否对您很重要,但为了确保使用 Saxon 9.5 我得到您在结果示例中发布的顺序,我不得不使用<xsl:copy-of select="for $n in current-group() return $n/name"/>而不是更短更常用的顺序<xsl:copy-of select="current-group()/name"/>

因此,该解决方案应该更有效,主要是通过对所有 input 进行分组node,当然然后只需使用 ofcurrent-group()而不是再次使用谓词选择节点。

于 2013-04-26T08:56:06.473 回答