2
votes

I have two xml files, with the same structure, and I'd like to generate a new xml file with the same structure based on their contents. For example:

File1.xml

<?xml version="1.0" encoding="UTF-8"?>
<coverage>
   <project timestamp="1369233123077" name="Project1">
      <metrics conditionals="664" methods="117" classes="13" files="9" coveredstatements="1554" />
   </project>
</coverage>

File2.xml

<?xml version="1.0" encoding="UTF-8"?>
<coverage>
   <project timestamp="1369224383368" name="Project1">
      <metrics conditionals="684" methods="122" classes="13" files="9" coveredstatements="1654" />
   </project>
</coverage>

The resulted file I hope to get, and it contains substractions of the identical attributes. File3.xml

<?xml version="1.0" encoding="UTF-8"?>
<coverage>
   <project timestamp1="1369233123077" timestamp2="1369224383368" name="Project1">
      <metrics conditionals="20" methods="5" classes="0" files="0" coveredstatements="100" />
   </project>
</coverage>

I tried XSL with File1.xml and managed to display the result as above, but I hoped to get a new XML file created on the hard drive. Is there a way to do it?

2

2 Answers

1
votes

You don't say if the solution needs to handle more than one project or not, so I've assumed the answer is "yes, there could be multiple projects". You also don't say if you can use XSLT 2.0 or are stuck with XSLT 1.0.

t:\ftemp>type file1.xml 
<?xml version="1.0" encoding="UTF-8"?>
<coverage>
   <project timestamp="1369233123077" name="Project1">
      <metrics conditionals="664" methods="117" classes="13" files="9" coveredstatements="1554" />
   </project>
</coverage>
t:\ftemp>type file2.xml 
<?xml version="1.0" encoding="UTF-8"?>
<coverage>
   <project timestamp="1369224383368" name="Project1">
      <metrics conditionals="684" methods="122" classes="13" files="9" coveredstatements="1654" />
   </project>
</coverage>
t:\ftemp>call xslt2 talleen.xsl talleen.xsl 
<?xml version="1.0" encoding="UTF-8"?>
<coverage>
   <project timestamp1="1369224383368"
            timestamp2="1369233123077"
            name="Project1">
      <metrics conditionals="20"
               methods="5"
               classes="0"
               files="0"
               coveredstatements="100"/>
   </project>
</coverage>

t:\ftemp>type talleen.xsl 
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

<xsl:key name="projects" match="project" use="@name"/>
<xsl:output indent="yes"/>

<xsl:template match="/">
  <xsl:apply-templates select="doc('file2.xml')/node()"/>
</xsl:template>

<xsl:template match="project">
  <xsl:variable name="other" select="key('projects',@name,doc('file1.xml'))"/>
  <project timestamp1="{@timestamp}" timestamp2="{$other/@timestamp}"
           name="{@name}">
    <metrics>
      <xsl:for-each select="metrics/@*">
        <xsl:attribute name="{name(.)}"
                       select=". - $other/metrics/@*[name()=name(current())]"/>
      </xsl:for-each>
    </metrics>
  </project>
</xsl:template>

<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done! 
0
votes

You're saying you've written the required XSLT code but you don't know how to save the result as a file on your hard disk?

That's then a question about the API of your chosen XSLT processor, so we need to know which XSLT processor you are using and how you are running it.