通过使用元素的相对位置来同步两个有点类似的XML文件

时间:2015-03-26 15:05:44

标签: xml xslt sync xslt-2.0

故事: 我有2个文件。 1有不正确的ID和不同的语言。我想将该文件中的名称和描述复制到另一个文件,但保持其他所有内容不受影响。

我有2个非常长的xml文件,看起来像这样:

<item>
     <itemtype id="1" classname="chair">
         <name>Chair</name>
         <description>Wooden chair</description>
     </itemtype>
</item>

所以我想更改该名称和描述,以匹配另一个文件中的信息。 (也可能是id) 有没有这样做的程序? 或者是一个可以做到的PHP代码?

文件1:

    <item>
     <itemtype id="1" classname="chair">
         <name>Chair</name>
         <description>Wooden chair</description>
     </itemtype>
</item>

相同的300倍,但具有不同的ID,名称和描述。

文件2:

    <item>
     <itemtype id="24" classname="chair">
         <name>Seat</name>
         <description>White wooden seat</description>
     </itemtype>
</item>

相同的300倍,但随机ID,名称和描述。

我想使用文件2,但我不能因为&#34; id&#34;是错的。这就是为什么我想使用文件1,并更改名称和描述以匹配文件2中的信息。

1 个答案:

答案 0 :(得分:0)

这是一个老问题,您现在可能已经解决了问题,但它仍处于打开状态且未删除,所以让我试一试。

你说:

  

我想使用文件2,但我不能因为&#34; id&#34;是错的。这就是为什么我想使用文件1,并更改名称和描述以匹配文件2中的信息。

来自评论:

  

我在一个xml文件中有300&#34; item&#34;:s,它具有唯一的&#34; id&#34;。通常,类名,名称和描述也不同

因此,这意味着我们拥有的四个字段,id,classname,name和description是不同的,不能用于从文件2中的文件1中查找项目。在您的描述中似乎唯一匹配的是两个文件中的项目数

由于必须某种方式将文件1中的项目与文件2进行逻辑匹配,因此唯一剩下的就是项目的相对位置。因此,对于使用XSLT的以下解决方案,我将假设以下要求:

  1. 从第一个
  2. 开始,从文件1中取出项目编号X.
  3. 创建浅表副本
  4. 使用文件1中的@id
  5. 在文件2中的相同位置X找到该项目
  6. 使用文件2中的类名,名称和说明
  7. 如果不是最后一条记录,请转到下一条记录X + 1并再次从步骤1开始。
  8. 在XSLT中,这非常简单:

    <xsl:param name="doc1" select="document('doc1.xml')" />
    <xsl:param name="doc2" select="document('doc2.xml')" />
    
    <xsl:template name="main">
        <xsl:apply-templates select="$doc1/*" />
    </xsl:template>
    
    <!-- identity transform, used by $doc1 and (parts of) $doc2 -->
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="itemtype">
        <xsl:variable name="pos" select="position()"/>
        <xsl:copy>
            <xsl:copy-of select="@id" />
            <xsl:attribute name="classname" 
                select="$doc2/item/itemtype[$pos]/@classname" />
            <xsl:apply-templates select="$doc2/item/itemtype[$pos]/*"/>
        </xsl:copy>
    </xsl:template>
    

    上面的代码与XSLT 1.0兼容,但它也适用于XSLT 2.0。您应该通过命名模板&#34; main&#34;启动样式表来调用它,并将这两个参数设置为XML文件的位置。

    它从文件1中尽可能多地复制,但复制@classname以及文件2中<itemtype>下的所有元素。

    如果您的要求比这更复杂,您当然可以修改上述样板代码。我没有测试代码(只是手工编写),但我相信它应该可行。