[xsl] Oracle XSU generic XSL

Subject: [xsl] Oracle XSU generic XSL
From: Cristobal Galiano Fernandez <c.galiano@xxxxx>
Date: Thu, 05 Apr 2001 21:52:56 +0200

Ough:

Te envio una XSL genérica para realizar el proceso de actualización de un
fichero XML con otro fichero XML.
La estructura de los dos ficheros XMl es la de Oracle XSU salvo el cambio de
atributo num por id.

Cheers

Cristóbal Galiano Fdez


1) Fichero XML que va a actualizarse (Fichero M)
<ROWSET>
    <ROW id="1">
  <NAME>Paul</NAME>
         <LASTNAME>Down</LASTNAME>
  <CITY>Sao Paulo</CITY>
  <STRING>M1</STRING>
    </ROW>
    <ROW id="2">
        <NAME>Peter</NAME>
        <LASTNAME>Flash</LASTNAME>
 <CITY>Curitiba</CITY>
 <STRING>M2</STRING>
    </ROW>
    <ROW id="4">
         <NAME>Name4</NAME>
         <LASTNAME>Moon</LASTNAME>
  <CITY>City4</CITY>
         <STRING>String4</STRING>
    </ROW>
    <ROW id="5">
         <NAME>Name5</NAME>
         <LASTNAME>Last</LASTNAME>
         <CITY>City5</CITY>
         <STRING>String5</STRING>
    </ROW>
</ROWSET>

2) Fichero XML que con el que actualizará el fichero M (Fichero U)
<ROWSET>
 <ROW id="1">
             <NAME>Name1 (Mod)</NAME>
      <STRING>String1 (Mod)</STRING>
 </ROW>
 <ROW id="2">
             <LASTNAME>Flash (Mod)</LASTNAME>
             <STRING>String2 (Mod)</STRING>
 </ROW>
 <ROW id="3">
             <NAME>Name3 (Alta)</NAME>
             <LASTNAME>Down</LASTNAME>
      <CITY>City (alta)</CITY>
      <STRING>String3 (Alta)</STRING>
 </ROW>
        <ROW id="5">
      <NAME>Name5 (Mod)</NAME>
             <STRING>String5 (Mod)</STRING>
 </ROW>
</ROWSET>

3) XSL

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- 2001-04-05. UpdateOracleXSU.XSL
     2001-04-05. CGF
     """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
     -Un Fichero XML (M) es actualizado por otro fichero XML (U)
         .Sólo se actualiza el texto,no los atributos
     -Requisitos:
         .No hay elementos con id duplicados ni en el fichero M ni el el U
         .Todas las filas del fichero que se va a actualizar (M) están completas

         .Los nombres de las columnas de cada fila del fichero de actualización
          (U) es un subset del set de columnas que representa la fila del
          fichero que se va a actuaizar (M)
         .Si una fila del fichero U su id no existe en el fichero M deberia de
          contener el set completo de columnas que representan al fichero M ya
          que se copiará tal cual.
     """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-->

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:msxsl="urn:schemas-microsoft-com:xslt">

    <xsl:output method="xml" indent="yes"/>

    <!-- Deberia asignarse dinámicamente en un entorno de producción -->
    <xsl:param name="FileUpdate" select="'UpdateOracleXSU-U.xml'" />

    <!-- Fichero de Actualizaciones a una variable -->
    <xsl:variable name="ROWSET" select="document($FileUpdate)/ROWSET" />

   <xsl:template match="/">
      <ROWSET>
          <xsl:call-template name="OriginalUpdatesCopias" />
          <xsl:call-template name="UpdateCopias" />
      </ROWSET>
   </xsl:template>

   <xsl:template name="OriginalUpdatesCopias">
       <!-- Del Fichero M:
               .Se actualizan aquellas filas cuyo id SI existe en el Fichero U
               .Se copian     aquellas filas cuyo id NO existe en el Fichero U
-->
       <xsl:apply-templates select="ROWSET/ROW" mode="OriginalUpdatesCopias" />
   </xsl:template>

   <xsl:template name="UpdateCopias">
       <!-- Del Fichero U:
               .Se copian     aquellas filas cuyo id NO existe en el Fichero M
-->
       <!--  Variable que contiene sólo los elemento <ROW @id=".."> sin
elementos
             descendientes del Fichero M -->
       <xsl:variable name="ROWids">
             <xsl:apply-templates select="ROWSET/ROW" mode="id" />
       </xsl:variable>
       <!-- Copias de Update (*R) Ini  $R=<xsl:copy-of select="$ROWids" /> Fin
-->

       <!-- Proceso todas las filas del fichero U
               .Paso como parámetro los id del fichero M -->
       <xsl:apply-templates select="$ROWSET/ROW" mode="UpdateCopias">
           <xsl:with-param name="ROW" select="msxsl:node-set($ROWids)/ROW" />
       </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="ROW" mode="OriginalUpdatesCopias" >
        <!--  <xsl:copy-of select="." /> -->

        <xsl:variable name="id" select="@id" />
        <xsl:choose>
             <xsl:when test="$ROWSET/ROW[@id=$id]"> <!-- Fila cuyo id existe en
el fichero U -->
                 <ROW id="{@id}">
                     <!-- Proceso la fila del fichero U -->
                     <xsl:apply-templates select="$ROWSET/ROW[@id=$id]"
mode="select">
                         <xsl:with-param name="rowM" select="." /> <!-- Paso
Fila del fichero M -->
                     </xsl:apply-templates>
                 </ROW>
             </xsl:when>
             <xsl:otherwise>
                 <xsl:copy-of select="."/>  <!-- Se copia del Original -->
             </xsl:otherwise>
         </xsl:choose>


   </xsl:template>

   <xsl:template match="ROW" mode="select" >
       <xsl:param name="rowM" />  <!-- Fila del fichero M -->
       <!-- Estoy procesando una fila del Ficho U -->
       <!-- (row-M=<xsl:copy-of select="$rowM" />)
       (row-U=<xsl:copy-of select="." />) -->

       <!-- Aplico templates a la fila del fichero M pasando como parámetro la
fila del fichero U -->
       <xsl:apply-templates select="$rowM" mode="update">
           <xsl:with-param name="rowU" select="." />
       </xsl:apply-templates>

   </xsl:template>

   <xsl:template match="ROW" mode="update" >
       <xsl:param name="rowU" />

        <!-- (Update row-U=<xsl:copy-of select="$rowU" />) -->
        <!-- Proceso cada columna del fichero M -->
        <xsl:for-each select="node()">
            <!-- [<xsl:value-of select="position()"/>-<xsl:value-of
select="local-name()"/>-<xsl:value-of select="."/>]
                 [Valor=<xsl:value-of select="position()"/>-<xsl:value-of
select="$rowU/*[local-name()]"/>] -->

            <xsl:variable name="col" select="local-name()" /> <!-- Nombre de la
columna del fichero M -->

            <xsl:choose>
                <!-- (Observar distinto ámbito,en ambos casos,de local-name())
-->
                <xsl:when test="$rowU/*[local-name() = $col]">
                    <!-- Si existe la columna en el fichero U se copia esta -->
                    <xsl:copy-of select="$rowU/*[local-name() = $col]"/>  <!--
Nodo actualizado -->
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="."/>  <!-- Columna del fichero M -->
                </xsl:otherwise>
            </xsl:choose>

        </xsl:for-each>

   </xsl:template>

   <xsl:template match="ROW" mode="id" >
      <ROW id="{@id}"></ROW> <!-- Obtengo el elemento ROW y el atributo id. No
hay desdendientes-->
   </xsl:template>

   <xsl:template match="ROW" mode="UpdateCopias">
       <xsl:param name="ROW" /> <!-- contiene sólo todos los id, sin las
columnas del fichero M -->
      <!-- Estoy procesando filas del fichero U -->
      <!-- $ROW=<xsl:copy-of select="$ROW" /> -->

        <xsl:variable name="id" select="@id" /> <!-- id del fichero U -->
         <xsl:choose>
             <xsl:when test="$ROW[@id=$id]"> <!-- Si existe la fila del fichero
U en el fichero M -->
                 <!-- No hago nada -->
             </xsl:when>
             <xsl:otherwise>
                 <xsl:copy-of select="."/>  <!-- Se copia al Original -->
             </xsl:otherwise>
         </xsl:choose>

   </xsl:template>

</xsl:stylesheet>



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread