简体   繁体   English

如何使用XSLT1.0合并两个xml文件

[英]How to merge two xml files using XSLT1.0

I am trying to merge two xml files using XSLT1.0. 我试图使用XSLT1.0合并两个xml文件。 I am trying to merge FileOne and Filetwo to merge to a new xml file. 我试图合并FileOne和Filetwo合并到一个新的XML文件。 The resultant xml should contain one element from file two based on the value from measurement tag. 结果xml应该包含来自文件2的一个元素,该元素基于来自measurement标签的值。 Any help would be greatly appreciated 任何帮助将不胜感激

Fileone.xml Fileone.xml

<Schedule name="NE3S">
    <Item scheduleId="1" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0001</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="15" minutes="0"/>
        </measPeriods>
    </Item>
    <Item scheduleId="2" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0002</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="60" minutes="0"/>
        </measPeriods>
    </Item>
</Schedule>

Filetwo.xml Filetwo.xml

<Schedule name="NE3S">
    <Item scheduleId="1" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
        <measurement>PGW0001</measurement>
    </measurements>
    <measPeriods>
        <period day="0" duration="0" hour="0" interval="60" minutes="0"/>
    </measPeriods>
    </Item>
    <Item scheduleId="2" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGD0001</measurement>
        </measurements>
    <measPeriods>
        <period day="0" duration="0" hour="0" interval="60" minutes="0"/>
    </measPeriods>
    </Item>
    <Item scheduleId="3" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0002</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="60" minutes="0"/>
        </measPeriods>
    </Item>
</Schedule>

My expected output is 我的预期产量是

<Schedule name="NE3S">
    <Item scheduleId="1" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0001</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="15" minutes="0"/>
        </measPeriods>
    </Item>
    <Item scheduleId="2" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGD0001</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="60" minutes="0"/>
        </measPeriods>
    </Item>
    <Item scheduleId="3" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0002</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="60" minutes="0"/>
        </measPeriods>
    </Item>
</Schedule>

please note that expected output 请注意预期的输出

<measPeriods>
  <period day="0" duration="0" hour="0" interval="15" minutes="0"/>
</measPeriods>

I tried the following code 我尝试了以下代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="fileName" select="'/opt/Filetwo.xml'" />
<xsl:param name="updates" select="document($fileName)" />

<xsl:variable name="updateMeasurement" select="$updates/Schedule/Item" />

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

<xsl:template match="Schedule">
    <xsl:copy>
      <xsl:apply-templates select="Item[not(measurements/measurement = $updateMeasurement/measurements/measurement)]" />
      <xsl:apply-templates select="/Schedule/Item//measurements" />
      <xsl:apply-templates select="$updates/Schedule/Item/measPeriods" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>


xsltproc merge.xslt /opt/Fileone.xml > /opt/FileThree.xml

my expected output should have the <measPeriods> tag from Fileone.xml if the value in <measurements>/<measurement> matches 如果<measurements>/<measurement>中的<measurements>/<measurement>匹配,我的预期输出应该具有来自Fileone.xml<measPeriods>标记

edited my solution to 编辑了我的解决方案

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0"
encoding="UTF-8" indent="yes"/>

<xsl:variable name="addresses"
select="document('/opt/esymac/extras/esymacstarter/schedule/MJ.netact.xml_backup')"/>
   <xsl:template match="/measSchedule">
        <measSchedule name="NE3S">
        <xsl:for-each select="scheduleItem">
           <xsl:variable name="id" select="@scheduleId"/>
           <xsl:variable name="startDate" select="@startDate"/>
           <xsl:variable name="stopDate" select="@stopDate"/>
           <xsl:variable name="day" select="measPeriods/period/@day"/>
           <xsl:variable name="duration" select="measPeriods/period/@duration"/>
           <xsl:variable name="hour" select="measPeriods/period/@hour"/>
           <xsl:variable name="minutes" select="measPeriods/period/@minutes"/>

           <xsl:variable name="interval"
select="$addresses/measSchedule/scheduleItem/measurements[$counterId =
@measurement]/measPeriods/@interval"/>
             <Item scheduleId="{$id}" startDate="{$startDate}" stopDate="{$stopDate}">
             <measurements>
                <measurement><xsl:value-of select="measurements/measurement"/></measurement>
             </measurements>
             <measPeriods>
                   <period day="{$day}" duration="{$duration}" hour="{$hour}" interval="{$interval}" minutes="{$minutes}"/>
             </measPeriods>
             </Item>
    </xsl:for-each>
</measSchedule>
</xsl:template>

</xsl:stylesheet>

now i am getting Item tag properly but 现在我正在获得Item标签但是

<period day="{$day}" duration="{$duration}" hour="{$hour}" interval="{$interval}" minutes="{$minutes}"/>

is still not proper 仍然不合适

From the input XMLs, it looks like Fileone.xml has a subset of records from the Filetwo.xml . 从输入个XML,它看起来像Fileone.xml具有从记录的子集Filetwo.xml An easier approach will be write the XSL and apply it on Filetwo.xml (since it has all the records and we have to replace only few) and access Fileone.xml using the document() function. 一种更简单的方法是编写XSL并将其应用于Filetwo.xml (因为它具有所有记录,我们只需要替换少数记录)并使用document()函数访问Fileone.xml

For the matching value of <measurement> , you can use the <xsl:choose></xsl:choose> to copy period from Fileone.xml and for the non-matching value, retain period from Filetwo.xml . 对于<measurement>的匹配值,可以使用<xsl:choose></xsl:choose>Fileone.xml复制period Fileone.xml ,对于不匹配的值,从Filetwo.xml保留period Filetwo.xml Below is the <xsl:choose> block. 下面是<xsl:choose>块。

<xsl:choose>
    <xsl:when test="$extSchedule/Item/measurements/measurement = current()/ancestor::Item/measurements/measurement">
        <xsl:copy-of select="$extSchedule/Item[measurements/measurement = current()/ancestor::Item/measurements/measurement]/measPeriods/period" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:apply-templates select="period" />
    </xsl:otherwise>
</xsl:choose>

Here current() is used to access the correct node and its corresponding sibling's measurement value. 这里current()用于访问正确的节点及其相应的兄弟measurement值。

The complete XSLT is as below 完整的XSLT如下

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:param name="fileName" select="document('Fileone.xml')" />
    <xsl:variable name="extSchedule" select="$fileName/Schedule" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="measPeriods">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="$extSchedule/Item/measurements/measurement = current()/ancestor::Item/measurements/measurement">
                    <xsl:copy-of select="$extSchedule/Item[measurements/measurement = current()/ancestor::Item/measurements/measurement]/measPeriods/period" />
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="period" />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

The output below shows the period for PGW0001 has been replaced with the corresponding node from Fileone.xml . 下面输出显示periodPGW0001已经被替换为从对应节点Fileone.xml

<Schedule name="NE3S">
    <Item scheduleId="1" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0001</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="15" minutes="0" />
        </measPeriods>
    </Item>
    <Item scheduleId="2" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGD0001</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="60" minutes="0" />
        </measPeriods>
    </Item>
    <Item scheduleId="3" startDate="2013-01-01" stopDate="2037-12-31">
        <measurements>
            <measurement>PGW0002</measurement>
        </measurements>
        <measPeriods>
            <period day="0" duration="0" hour="0" interval="60" minutes="0" />
        </measPeriods>
    </Item>
</Schedule>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM