Find differences between two XMLs using XSL Transform

╄→гoц情女王★ 提交于 2019-12-23 04:35:53

问题


I have two files and I am working on writing the transform

I would like the transform to return the names of the people whose details have been modified (address,age) and the names of the people who do not exist in file 1 but present in file 2 as well as people who exist in file 1 but do not exist in file 2.

I have tried the following but it can only compare, it cannot find any addition or deletion

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:param name="path-to-file2" select="'file2.xml'"/>

<xsl:template match="/row">
<xsl:if test="address != document($path-to-file2)/rowset/row/address">
    <xsl:value-of select="name"/>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

File 1:

<rowset>
<row>
    <name>kathy</name>
    <address>Cameron blvd</address>
    <age>12</age>
</row>
<row>
    <name>james</name>
    <address>superior blvd</address>
    <age>15</age>
</row>
</rowset>

File 2:

<rowset>
<row>
    <name>kathy</name>
    <address>Cameron blvd Las Vegas</address>
    <age>14</age>
</row>
<row>
    <name>james</name>
    <address>superior blvd</address>
    <age>15</age>
</row>
<row>
    <name>Henry</name>
    <address>Huron blvd</address>
    <age>18</age>
</row>
</rowset>

In above scenario I would like the transform to return:

Kathy, Henry


回答1:


Firstly, it may help if you defined two variables to hold the references to the rows in each file

<xsl:variable name="file1Rows" select="/rowset/row" />
<xsl:variable name="file2Rows" select="document($path-to-file2)/rowset/row" />

Then, to get rows added (in file 2), do this

<xsl:apply-templates select="$file2Rows[not(name = $file1Rows/name)]" />

To get deletions, just reverse this...

<xsl:apply-templates select="$file1Rows[not(name = $file2Rows/name)]" />

Getting changes, takes a bit of extra work, but can be done like this...

<xsl:for-each select="$file1Rows">
    <xsl:apply-templates select="$file2Rows[name = current()/name and (address != current()/address or age != current()/age)]" />
</xsl:for-each>

Putting this altogether gives this...

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

<xsl:param name="path-to-file2" select="'file2.xml'"/>

<xsl:variable name="file1Rows" select="/rowset/row" />
<xsl:variable name="file2Rows" select="document($path-to-file2)/rowset/row" />

<xsl:template match="/*">
    <xsl:apply-templates select="file1/rowset" />
</xsl:template>

<xsl:template match="rowset">
    <additions>
        <xsl:apply-templates select="$file2Rows[not(name = $file1Rows/name)]" />
    </additions>
    <deletions>
        <xsl:apply-templates select="$file1Rows[not(name = $file2Rows/name)]" />
    </deletions>
    <changes>
    <xsl:for-each select="$file1Rows">
        <xsl:apply-templates select="$file2Rows[name = current()/name and (address != current()/address or age != current()/age)]" />
    </xsl:for-each>
    </changes>
</xsl:template>

<xsl:template match="row">
    <xsl:copy-of select="name" />
</xsl:template>

</xsl:stylesheet>



回答2:


XSLT is case sensitive

change your code as input also add '//' in xpath

<xsl:template match="/row">
<xsl:if test="address != document($path-to-file2)//rowset/row/address">
    <xsl:value-of select="name"/>
</xsl:if>
</xsl:template>


来源:https://stackoverflow.com/questions/57266554/find-differences-between-two-xmls-using-xsl-transform

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!