Merge two xml ... again

My knowledge to xslt is limited, but I've googeled for hours and trying many different scripts without luck. Here is the plot: We have a xml database file on our server that a software will read every time we start a software. We are about 10 users that use this file. new entries are stored in a similar file locally, and we need to update the server file to include our new locally stored entries weekly. I have made a upload feature to upload local files. The uploaded file is stored in a directory above the database file. The name is the same for both files, but stored in different directories.

Here is the closest thing I've come up with, copying a former solutin from this site, just changing the names. Exemple files here is with few entries for testing purpose only.

"Original" XML: companyroutes.xml

 <?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 
<companyroutes>
  <route name="ENGMEKCH">ENGM OKSAT L996 SVD EKCH</route>

</companyroutes>

Uploaded XML: /upload/companyroutes.xml

<?xml version="1.0" encoding="utf-8"?>
<companyroutes>
   <route name="ENVAENBR">ENVA GEVLI Z108 ROXET ENBR</route>
   <route name="ENGMEKCH">ENGM OKSAT L996 SVD EKCH</route>
   <route name="ABCDEFGH">ABCD TULLA L666 BAREN EFGH</route>

</companyroutes>

Here is the xsl merge script: merge2.xsl

<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="'/upload/companyroutes.xml'" />
  <xsl:param name="updates" select="document($fileName)" />

  <xsl:variable name="updateRoute" select="$updates/companyroutes/route" />

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

  <xsl:template match="companyroutes">
    <xsl:copy>
      <xsl:apply-templates select="route[not(@id = $updateRoute/@id)]" />
      <xsl:apply-templates select="$updateRoute" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Two other functions I need included is only unique Childs beeing copied to the original and the ability to still view the original file in browser like we do today on this url: [http://www.xxxxx.org/cr/companyroutes.xml][1] When I have tried inserting link to second .xsl file doing merging, I cannot see any info on the url.

Here is the cr.xsl that transfor the xml to HTML table on webpage:

<?xml version="1.0" encoding="ISO-8859-1"?>

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

<xsl:template match="/">
  <html>
  <body>
  <h2>BBL - CompanyRoutes</h2>
  <table border="1" cellspacing="0" cellpadding="2">
    <tr>
      <th>Route Name</th>
      <th>Route</th>
    </tr>
    <xsl:for-each select="//route">
    <tr>
      <td><xsl:value-of select="./@name"/></td>
      <td><xsl:value-of select="./text()"/></td>
    </tr>
    </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

Answers


You have two problems here.

Firstly, in your merge XSLT you are doing this

<xsl:apply-templates select="route[not(@id = $updateRoute/@id)]" /> 

You are matching on @id attributes, but in the XML it appears to be the @name attribute that should be used. Therefore the statement should look like this

 <xsl:apply-templates select="route[not(@name = $updateRoute/@name)]" /> 

You also talk about viewing it in a browser, and looking at XML you have linked to, you have two xml-stylesheet processing instructions at the top of your XML (although you only show one in your XML sample in your question)

<?xml-stylesheet type="text/xsl" href="cr.xsl"?>
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 

This suggests you may be expecting two transformations to be applied. With the cr.xsl applying to the result of the merge2.xsl transformation. I do not believe this is possible in this way. Even if it was possible, this will not overwrite the original XML. It is creating a whole new XML document display.

What you can do, is merge the two XSLT stylesheets into one, and use that, if your purely want to see the results of the merge in the browser

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

  <xsl:variable name="updateRoute" select="$updates/companyroutes/route"/>

  <xsl:template match="companyroutes">
    <html>
      <body>
        <h2>BBL - CompanyRoutes</h2>
        <table border="1" cellspacing="0" cellpadding="2">
          <tr>
            <th>Route Name</th>
            <th>Route</th>
          </tr>
          <xsl:for-each select="route[not(@name = $updateRoute/@name)]|$updateRoute">
            <xsl:sort select="@name"/>
            <tr>
              <td>
                <xsl:value-of select="./@name"/>
              </td>
              <td>
                <xsl:value-of select="./text()"/>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Of course, if you did actually want to overwrite the original XML with the merge, then this is not possible using this approach. Adding xml-stylesheet processing instructions in the XML will not cause the original XML to be overwritten in anyway. (Bear in mind the transformation is being done on the client, in the browser, but your files are being stored on a server.)

You are going to have to investigate doing the transformations on the server, using a server language such as PHP, or ASP.Net, or something else, depending on what architecture you are currently using.


Need Your Help

Javascript not loading html into divs

javascript jquery html load

Why this doesn't work? It's supposed to load content of another html file into DIV with bottom id