XSLT - 合并2个不具有通用ID的XML文件

时间:2012-06-22 10:39:02

标签: xml xslt

我想加入两个xml文件,如下图所示。但是我的问题是如何使用ID来加入。我想做关于POSITION而不是id的加入。你会如何为以下文件执行此操作?

文件1:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <data>
    <title>Title1</title>
    <description>Description1</description>
  </data>

  <data>
    <title>Title2</title>
    <description>Description2</description>
  </data>
</catalog>

文件2:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <data>
    <author>Author1</author>
    <date>12/34/5678</date>
  </data>

  <data>
    <author>Author2</author>
    <date>87/65/4321</date>
  </data>
</catalog>

输出:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <data>
    <title>Title1</title>
    <description>Description1</description>
    <author>Author1</author>
    <date>12/34/5678</date>
  </data>

  <data>
    <title>Title2</title>
    <description>Description2</description>
    <author>Author2</author>
    <date>87/65/4321</date>
  </data>
</catalog>

如果您使用下面的XSLT有一个共同的ID字段,我知道如何执行此操作,但是您如何加入POSITION?

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" />
  <xsl:variable name="with" select="'File2.xml'" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="scene">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
      <xsl:variable name="info" select="document($with)/catalog/data[id=current()/id]/." />
      <xsl:for-each select="$info/*">
        <xsl:if test="name()!='myid'">
          <xsl:copy-of select="." />
        </xsl:if>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:transform>

3 个答案:

答案 0 :(得分:1)

尝试

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

<xsl:param name="url2" select="'input2.xml'"/>
<xsl:variable name="data2" select="document($url2)/catalog/data"/>

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="data">
  <xsl:variable name="pos" select="position()"/>
  <xsl:copy>
    <xsl:apply-templates select="@* | * | $data2[$pos]/*"/>
  </xsl:copy>
</xsl:template>

答案 1 :(得分:1)

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" />
    <xsl:variable name="with" select="'File2.xml'" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="data">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
            <!--Determine the index of the current data element in this document.
                   Note: using position() may not always yield the desired number 
                         because other siblings (text(), comment(), 
                         processing-instruction(), 
                         or other elements) would affect position().
                         Also, counting preceeding-siblings that are data 
                         elements, not just any element. -->
            <xsl:apply-templates 
                select="document($with)
                /catalog
                /data[position() 
                       = count(current()/preceding-sibling::data)+1]
                /*[name()!='myid']" />
                <!--kept filter for `myid` elements from example stylesheet, 
                    remove if not needed --> 
        </xsl:copy>
    </xsl:template>
</xsl:transform>

答案 2 :(得分:1)

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" />
  <xsl:variable name="with" select="'File2.xml'" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="data">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
      <!-- using count to get the current position of the elements is safer --> 
      <xsl:copy-of select="document($with)/catalog/
         data[position()=count(current()/preceding-sibling::*) + 1]/*"/>
    </xsl:copy>
  </xsl:template>
</xsl:transform>