问题
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