home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / autoinstall / xslt / merge.xslt
Encoding:
Extensible Markup Language  |  2006-11-29  |  13.1 KB  |  308 lines

  1. <?xml version="1.0"?>
  2.  
  3. <!--
  4.    Merging two XML files
  5.    Version 1.6
  6.    LGPL (c) Oliver Becker, 2002-07-05
  7.    obecker@informatik.hu-berlin.de
  8. -->
  9.  
  10. <xslt:transform version="1.0"
  11.                 xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
  12.                 xmlns:m="http://informatik.hu-berlin.de/merge"
  13.                 exclude-result-prefixes="m">
  14.  
  15. <xslt:output method="xml" cdata-section-elements="list source file_contents YAST_INFO SYS_SW_SELLIST SYS_SW_ADDLIST SYS_PCMCIA_MODULES SYS_RC_CONFIG_VARS NET_IP_CONFIG SYS_PART_sda SYS_PART_sdb SYS_PART_sdc SYS_PART_sdd SYS_PART_hda SYS_PART_hdb SYS_PART_hdc SYS_PART_hdd USERLIST INETDLIST ETC_HOSTS MODULES_CONF GROUPLIST SYS_SW_AUXLIST ROUTES"/>
  16.  
  17. <!-- Normalize the contents of text, comment, and processing-instruction
  18.      nodes before comparing?
  19.      Default: yes -->
  20. <xslt:param name="normalize" select="'yes'" />
  21.  
  22. <!-- Don't merge elements with this (qualified) name -->
  23. <xslt:param name="dontmerge" />
  24. <xslt:param name="dontmerge1" />
  25. <xslt:param name="dontmerge2" />
  26. <xslt:param name="dontmerge3" />
  27. <xslt:param name="dontmerge4" />
  28. <xslt:param name="dontmerge5" />
  29. <xslt:param name="dontmerge6" />
  30. <xslt:param name="dontmerge7" />
  31. <xslt:param name="dontmerge8" />
  32. <xslt:param name="dontmerge9" />
  33. <xslt:param name="dontmerge10" />
  34.  
  35. <!-- If set to true, text nodes in file1 will be replaced -->
  36. <xslt:param name="replace" select="false()" />
  37.  
  38. <!-- Variant 1: Source document looks like
  39.      <?xml version="1.0"?>
  40.      <merge xmlns="http://informatik.hu-berlin.de/merge">
  41.         <file1>file1.xml</file1>
  42.         <file2>file2.xml</file2>
  43.      </merge>         
  44.      The transformation sheet merges file1.xml and file2.xml.
  45. -->
  46. <xslt:template match="m:merge" >
  47.    <xslt:variable name="file1" select="string(m:file1)" />
  48.    <xslt:variable name="file2" select="string(m:file2)" />
  49.    <xslt:message>
  50.       <xslt:text />Merging '<xslt:value-of select="$file1" />
  51.       <xslt:text />' and '<xslt:value-of select="$file2"/>'<xslt:text />
  52.    </xslt:message>
  53.    <xslt:if test="$file1='' or $file2=''">
  54.       <xslt:message terminate="yes">
  55.          <xslt:text>No files to merge specified</xslt:text>
  56.       </xslt:message>
  57.    </xslt:if>
  58.    <xslt:call-template name="m:merge">
  59.       <xslt:with-param name="nodes1" select="document($file1,/*)/node()" />
  60.       <xslt:with-param name="nodes2" select="document($file2,/*)/node()" />
  61.    </xslt:call-template>
  62. </xslt:template>
  63.  
  64.  
  65. <!-- Variant 2:
  66.      The transformation sheet merges the source document with the
  67.      document provided by the parameter "with".
  68. -->
  69. <xslt:param name="with" />
  70.  
  71. <xslt:template match="*">
  72. <!--
  73.    <xslt:message>
  74.       <xslt:text />Merging input with '<xslt:value-of select="$with"/>
  75.       <xslt:text>'</xslt:text>
  76.    </xslt:message>
  77. -->
  78.    <xslt:if test="string($with)=''">
  79.       <xslt:message terminate="yes">
  80.          <xslt:text>No input file specified (parameter 'with')</xslt:text>
  81.       </xslt:message>
  82.    </xslt:if>
  83.  
  84.    <xslt:call-template name="m:merge">
  85.       <xslt:with-param name="nodes1" select="/node()" />
  86.       <xslt:with-param name="nodes2" select="document($with,/*)/node()" />
  87.    </xslt:call-template>
  88. </xslt:template>
  89.  
  90.  
  91. <!-- ============================================================== -->
  92.  
  93. <!-- The "merge" template -->
  94. <xslt:template name="m:merge">
  95.    <xslt:param name="nodes1" />
  96.    <xslt:param name="nodes2" />
  97.  
  98.    <xslt:choose>
  99.       <!-- Is $nodes1 resp. $nodes2 empty? -->
  100.       <xslt:when test="count($nodes1)=0">
  101.          <xslt:copy-of select="$nodes2" />
  102.       </xslt:when>
  103.       <xslt:when test="count($nodes2)=0">
  104.          <xslt:copy-of select="$nodes1" />
  105.       </xslt:when>
  106.  
  107.       <xslt:otherwise>
  108.          <!-- Split $nodes1 and $nodes2 -->
  109.          <xslt:variable name="first1" select="$nodes1[1]" />
  110.          <xslt:variable name="rest1" select="$nodes1[position()!=1]" />
  111.          <xslt:variable name="first2" select="$nodes2[1]" />
  112.          <xslt:variable name="rest2" select="$nodes2[position()!=1]" />
  113.          <!-- Determine type of node $first1 -->
  114.          <xslt:variable name="type1">
  115.             <xslt:apply-templates mode="m:detect-type" select="$first1" />
  116.          </xslt:variable>
  117.  
  118.          <!-- Compare $first1 and $first2 -->
  119.          <xslt:variable name="diff-first">
  120.             <xslt:call-template name="m:compare-nodes">
  121.                <xslt:with-param name="node1" select="$first1" />
  122.                <xslt:with-param name="node2" select="$first2" />
  123.             </xslt:call-template>
  124.          </xslt:variable>
  125.  
  126.          <xslt:choose>
  127.             <!-- $first1 != $first2 -->
  128.             <xslt:when test="$diff-first='!'">
  129.                <!-- Compare $first1 and $rest2 -->
  130.                <xslt:variable name="diff-rest">
  131.                   <xslt:for-each select="$rest2">
  132.                      <xslt:call-template name="m:compare-nodes">
  133.                         <xslt:with-param name="node1" select="$first1" />
  134.                         <xslt:with-param name="node2" select="." />
  135.                      </xslt:call-template>
  136.                   </xslt:for-each>
  137.                </xslt:variable>
  138.       
  139.                <xslt:choose>
  140.                   <!-- $first1 is in $rest2 and 
  141.                        $first1 is *not* an empty text node  -->
  142.                   <xslt:when test="contains($diff-rest,'=') and
  143.                                       not($type1='text' and
  144.                                           normalize-space($first1)='')">
  145.                      <!-- determine position of $first1 in $nodes2
  146.                           and copy all preceding nodes of $nodes2 -->
  147.                      <xslt:variable name="pos" 
  148.                            select="string-length(substring-before(
  149.                                                 $diff-rest,'=')) + 2" />
  150.                      <xslt:copy-of 
  151.                            select="$nodes2[position() < $pos]" />
  152.                      <!-- merge $first1 with its equivalent node -->
  153.                      <xslt:choose>
  154.                         <!-- Elements: merge -->
  155.                         <xslt:when test="$type1='element'">
  156.                            <xslt:element name="{name($first1)}" 
  157.                                          namespace="{namespace-uri($first1)}">
  158.                               <xslt:copy-of select="$first1/namespace::*" />
  159.                               <xslt:copy-of select="$first2/namespace::*" />
  160.                               <xslt:copy-of select="$first1/@*" />
  161.                               <xslt:call-template name="m:merge">
  162.                                  <xslt:with-param name="nodes1" 
  163.                                        select="$first1/node()" />
  164.                                  <xslt:with-param name="nodes2" 
  165.                                        select="$nodes2[position()=$pos]/node()" />
  166.                               </xslt:call-template>
  167.                            </xslt:element>
  168.                         </xslt:when>
  169.                         <!-- Other: copy -->
  170.                         <xslt:otherwise>
  171.                            <xslt:copy-of select="$first1" />
  172.                         </xslt:otherwise>
  173.                      </xslt:choose>
  174.       
  175.                      <!-- Merge $rest1 and rest of $nodes2 -->
  176.                      <xslt:call-template name="m:merge">
  177.                         <xslt:with-param name="nodes1" select="$rest1" />
  178.                         <xslt:with-param name="nodes2" 
  179.                               select="$nodes2[position() > $pos]" />
  180.                      </xslt:call-template>
  181.                   </xslt:when>
  182.  
  183.                   <!-- $first1 is a text node and replace mode was
  184.                        activated -->
  185.                   <xslt:when test="$type1='text' and $replace">
  186.                      <xslt:call-template name="m:merge">
  187.                         <xslt:with-param name="nodes1" select="$rest1" />
  188.                         <xslt:with-param name="nodes2" select="$nodes2" />
  189.                      </xslt:call-template>
  190.                   </xslt:when>
  191.  
  192.                   <!-- else: $first1 is not in $rest2 or
  193.                        $first1 is an empty text node -->
  194.                   <xslt:otherwise>
  195.                      <xslt:copy-of select="$first1" />
  196.                      <xslt:call-template name="m:merge">
  197.                         <xslt:with-param name="nodes1" select="$rest1" />
  198.                         <xslt:with-param name="nodes2" select="$nodes2" />
  199.                      </xslt:call-template>
  200.                   </xslt:otherwise>
  201.                </xslt:choose>
  202.             </xslt:when>
  203.  
  204.             <!-- else: $first1 = $first2 -->
  205.             <xslt:otherwise>
  206.                <xslt:choose>
  207.                   <!-- Elements: merge -->
  208.                   <xslt:when test="$type1='element'">
  209.                      <xslt:element name="{name($first1)}" 
  210.                                    namespace="{namespace-uri($first1)}">
  211.                         <xslt:copy-of select="$first1/namespace::*" />
  212.                         <xslt:copy-of select="$first2/namespace::*" />
  213.                         <xslt:copy-of select="$first1/@*" />
  214.                         <xslt:call-template name="m:merge">
  215.                            <xslt:with-param name="nodes1" 
  216.                                             select="$first1/node()" />
  217.                            <xslt:with-param name="nodes2" 
  218.                                             select="$first2/node()" />
  219.                         </xslt:call-template>
  220.                      </xslt:element>
  221.                   </xslt:when>
  222.                   <!-- Other: copy -->
  223.                   <xslt:otherwise>
  224.                      <xslt:copy-of select="$first1" />
  225.                   </xslt:otherwise>
  226.                </xslt:choose>
  227.  
  228.                <!-- Merge $rest1 and $rest2 -->
  229.                <xslt:call-template name="m:merge">
  230.                   <xslt:with-param name="nodes1" select="$rest1" />
  231.                   <xslt:with-param name="nodes2" select="$rest2" />
  232.                </xslt:call-template>
  233.             </xslt:otherwise>
  234.          </xslt:choose>
  235.       </xslt:otherwise>
  236.    </xslt:choose>
  237. </xslt:template>
  238.  
  239.  
  240. <!-- Comparing single nodes: 
  241.      if $node1 and $node2 are equivalent then the template creates a 
  242.      text node "=" otherwise a text node "!" -->
  243. <xslt:template name="m:compare-nodes">
  244.    <xslt:param name="node1" />
  245.    <xslt:param name="node2" />
  246.    <xslt:variable name="type1">
  247.       <xslt:apply-templates mode="m:detect-type" select="$node1" />
  248.    </xslt:variable>
  249.    <xslt:variable name="type2">
  250.       <xslt:apply-templates mode="m:detect-type" select="$node2" />
  251.    </xslt:variable>
  252.  
  253.    <xslt:choose>
  254.       <!-- Are $node1 and $node2 element nodes with the same name? -->
  255.       <xslt:when test="$type1='element' and $type2='element' and
  256.                        local-name($node1)=local-name($node2) and
  257.                        namespace-uri($node1)=namespace-uri($node2) and
  258.                        name($node1)!=$dontmerge and name($node2)!=$dontmerge and 
  259.                        name($node1)!=$dontmerge1 and name($node2)!=$dontmerge1 and 
  260.                        name($node1)!=$dontmerge2 and name($node2)!=$dontmerge2 and 
  261.                        name($node1)!=$dontmerge3 and name($node2)!=$dontmerge3 and 
  262.                        name($node1)!=$dontmerge4 and name($node2)!=$dontmerge4 and 
  263.                        name($node1)!=$dontmerge5 and name($node2)!=$dontmerge5 and 
  264.                        name($node1)!=$dontmerge6 and name($node2)!=$dontmerge6 and 
  265.                        name($node1)!=$dontmerge7 and name($node2)!=$dontmerge7 and 
  266.                        name($node1)!=$dontmerge8 and name($node2)!=$dontmerge8 and 
  267.                        name($node1)!=$dontmerge9 and name($node2)!=$dontmerge9 and 
  268.                        name($node1)!=$dontmerge10 and name($node2)!=$dontmerge10">
  269.          <!-- Comparing the attributes -->
  270.          <xslt:variable name="diff-att">
  271.             <!-- same number ... -->
  272.             <xslt:if test="count($node1/@*)!=count($node2/@*)">.</xslt:if>
  273.             <!-- ... and same name/content -->
  274.             <xslt:for-each select="$node1/@*">
  275.                <xslt:if test="not($node2/@*
  276.                         [local-name()=local-name(current()) and 
  277.                          namespace-uri()=namespace-uri(current()) and 
  278.                          .=current()])">.</xslt:if>
  279.             </xslt:for-each>
  280.          </xslt:variable>
  281.          <xslt:choose>
  282.             <xslt:when test="string-length($diff-att)!=0">!</xslt:when>
  283.             <xslt:otherwise>=</xslt:otherwise>
  284.          </xslt:choose>
  285.       </xslt:when>
  286.  
  287.       <!-- Other nodes: test for the same type and content -->
  288.       <xslt:when test="$type1!='element' and $type1=$type2 and
  289.                        name($node1)=name($node2) and 
  290.                        ($node1=$node2 or 
  291.                           ($normalize='yes' and
  292.                            normalize-space($node1)=
  293.                            normalize-space($node2)))">=</xslt:when>
  294.  
  295.       <!-- Otherwise: different node types or different name/content -->
  296.       <xslt:otherwise>!</xslt:otherwise>
  297.    </xslt:choose>
  298. </xslt:template>
  299.  
  300.  
  301. <!-- Type detection, thanks to M. H. Kay -->
  302. <xslt:template match="*" mode="m:detect-type">element</xslt:template>
  303. <xslt:template match="text()" mode="m:detect-type">text</xslt:template>
  304. <xslt:template match="comment()" mode="m:detect-type">comment</xslt:template>
  305. <xslt:template match="processing-instruction()" mode="m:detect-type">pi</xslt:template>
  306.  
  307. </xslt:transform>
  308.