在unix中使用XSLT合并2个xml文件

时间:2015-05-21 09:42:27

标签: xml unix xslt merge

我有2个XML文件,如下所示:

File1.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schedule name="myOffice">
  <taskItem taskId="1" startDate="2013-01-01" stopDate="2037-12-31">
    <measurements>
      <measurement>USD</measurement>
    </measurements>
    <timings>
      <period day="0" duration="0" hour="0" interval="28" minutes="0"/>
    </timings>
  </taskItem>
  <taskItem taskId="2" startDate="2013-01-01" stopDate="2037-12-31">
    <measurements>
      <measurement>Rupee</measurement>
    </measurements>
    <timings>
      <period day="0" duration="0" hour="0" interval="15" minutes="0"/>
    </timings>
  </taskItem>
</Schedule>

File2.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schedule name="myOffice">
  <taskItem taskId="1" startDate="2015-12-01" stopDate="2037-12-31">
    <measurements>
      <measurement>Rupee</measurement>
    </measurements>
    <timings>
      <period day="5" duration="10" hour="0" interval="20" minutes="0"/>
    </timings>
  </taskItem>
</Schedule>

我正在使用XSLT获取以下输出:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Schedule name="myOffice">
  <taskItem taskId="1" startDate="2013-01-01" stopDate="2037-12-31">
    <measurements>
      <measurement>USD</measurement>
    </measurements>
    <timings>
      <period day="0" duration="0" hour="0" interval="28" minutes="0"/>
    </timings>
  </taskItem>
  <taskItem taskId="2" startDate="2013-01-01" stopDate="2037-12-31">
    <measurements>
      <measurement>Rupee</measurement>
    </measurements>
    <timings>
      <period day="5" duration="10" hour="0" interval="20" minutes="0"/>
    </timings>
  </taskItem>
</Schedule>

但是把它作为输出:

<Schedule name="myOffice">
  <taskItem taskId="1" startDate="2015-12-01" stopDate="2037-12-31">
    <measurements>
      <measurement>Rupee</measurement>
    </measurements>
    <timings>
      <period day="5" duration="10" hour="0" interval="20" minutes="0"/>
    </timings>
  </taskItem>
</Schedule>

我无法到达落后的地方......

我的想法是,根据字段Measurement,我必须在stopDatetaskItemday,{{1}更新属性duration hour标记中的{},intervalminutes

我的XSLT文件是

period

我正在unix中执行命令,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" omit-xml-declaration="yes"/>

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

  <xsl:template match="taskItem//measurement">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()" />
      <xsl:apply-templates
        select="document('file1.xml')
              /Schedule/taskItem/timings/period[@day = current()/../../timings/period/@day and
                                                @duration = current()/../../timings/period/@duration and 
                                                @hour = current()/../../timings/period/@hour and
                                                @interval = current()/../../timings/period/@interval and
                                                @minutes = current()/../../timings/period/@minutes]/*" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

你想做的事:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes"/>

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

<xsl:template match="timings">
    <xsl:variable name="match" select="document('file2.xml')/Schedule/taskItem[measurements/measurement=current()/../measurements/measurement]/timings"/>
    <xsl:choose>
        <xsl:when test="$match">
            <xsl:copy-of select="$match"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

并指定file1.xml作为要处理的文件。

答案 1 :(得分:1)

根据我的理解,这是我的(详细)解决方案。我明确更新了每个属性/字段,以便您可以调整此解决方案以使其适应您的需求。来自taskItem的taskId和startDate取自file1.xml。 stopDate和时序来自file2.xml。您必须使用file1.xml作为参数调用此XSLT表。

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" omit-xml-declaration="yes"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  <!-- For all taskItem in file1.xml -->
  <xsl:template match="taskItem">
    <!-- Get all taskItems from file2.xml -->
    <xsl:variable name="tiother" select="document('file2.xml')/Schedule/taskItem" />
    <!-- Get measurement text from current and other taskItems (from file1.xml and file2.xml) -->
    <xsl:variable name="namethis" select="./measurements/measurement/text()" />
    <xsl:variable name="nameother" select="$tiother/measurements/measurement/text()" />
    <xsl:choose>
      <!-- if the measurement texts are the same -->
      <xsl:when test="$namethis = $nameother">
        <!-- Yes ? create a new taskItem updated -->
        <xsl:element name="taskItem">
          <!-- Get taskId from the current task item (the one in file1.xml) -->
          <xsl:attribute name="taskId"><xsl:value-of select="./@taskId"/></xsl:attribute>
          <!-- Get startDate from the current task item (the one in file1.xml) -->
          <xsl:attribute name="startDate"><xsl:value-of select="./@startDate"/></xsl:attribute>
          <!-- Get stopDate from the other task item (the one in file2.xml) -->
          <xsl:attribute name="stopDate"><xsl:value-of select="$tiother/@stopDate"/></xsl:attribute>
          <!-- Get the measurements from the current task item (the one in file1.xml) -->
          <xsl:copy-of select="./measurements"/>
          <!-- Get the timings from the other task item (the one in file2.xml) -->
          <xsl:copy-of select="$tiother/timings"/>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <!-- No ? just copy the current taskItem -->
        <xsl:copy-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>