Pregunta

Estoy utilizando XSLT y XML.

Lo primero que voy a trabajar en dos XML.

Primera XML:

<?xml version="1.0"?>
<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0" ID="tcm:232-83752-2" Managed="10682">  
  <tcm:Item ID="tcm:232-564598" Title="010 News Mapping"/>
  <tcm:Item ID="tcm:232-564599" Title="020 CUGOs"/>
  <tcm:Item ID="tcm:232-614307" Title="030 Reserved Urls"/>
</tcm:ListItems>

La Segundo XML lo conseguiremos usando encima ID es decir tcm: 232-564.598 etc, a continuación es uno de los xml para ID tcm: 232 a 564598 y otros IDs a tener mismo tipo de XML.

<tcm:Component ID="tcm:229-564598" IsEditable="false" xmlns:tcm="http://www.tridion.com/ContentManager/5.0" xmlns:xlink="http://www.w3.org/1999/xlink">
  <tcm:Data>
    <tcm:Content>
      <MappingCollection xmlns="uuid:922EEC29-2DE3-4BA1-A46A-A300CB8FA85F">
        <VanityUrl>
          <old>mbp</old>
          <new>/SessionHandler.aspx?pageurl=/BP.aspx&amp;pub=/english&amp;section=IBE&amp;j=f</new>
          <dateAdded>2010-05-03T14:45:00</dateAdded>
          <comments> News mapping </comments>
        </VanityUrl>
        <VanityUrl>
          <old>about/news</old>
          <new>about/news/news.aspx</new>
          <dateAdded>2010-05-03T14:45:00</dateAdded>
          <comments> News mapping </comments>
        </VanityUrl>
      </MappingCollection>
    </tcm:Content>
  </tcm:Data>
</tcm:Component>

Me tratando de conseguir a continuación formato XML utilizando por encima de ambas XMLs.

<?xml version="1.0" encoding="UTF-8"?>
<mappings>
    <!-- News mapping -->
    <mapping old="mbp" new="/SessionHandler.aspx?pageurl=/BP.aspx&amp;pub=/english&amp;section=IBE&amp;j=f"/>
    <mapping old="about/news" new="about/news/news.aspx"/>
    <!-- CUGO's-->
    <mapping old="/nhs" new="/cugo.aspx?promoCode=UKNHS01&amp;pub=/uk/english"/>
    <mapping old="/hk/ukstudentfare" new="/cugo.aspx?promoCode=HKSTU10&amp;pub=/hk/Chinese"/>
</mappings> 

Y aquí es donde mi XSLT Estoy intentando generado el formato XML anterior pero no está funcionando para mí. tenga en cuenta lo primero es XML XML principal que será transformada mediante el siguiente XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tcm="http://www.tridion.com/ContentManager/5.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:em="http://www.espire.com/tridion/schemas" xmlns:tcmse="http://www.tridion.com/ContentManager/5.1/TcmScriptAssistant" exclude-result-prefixes="em xlink tcmse tcm">
  <xsl:output method="xml" version="1.0" encoding="UTF-16" indent="yes"/>
  <!-- root match-->
  <xsl:template match="tcm:ListItems">
    <mappings>
      <xsl:apply-templates select="tcm:Item"/>
    </mappings>
  </xsl:template>
  <xsl:template match="tcm:Item">
      <xsl:variable name="doc" select="document(@ID)"/>
    <xsl:if test="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments">
      <xsl:comment>
        <xsl:value-of select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments"/>
      </xsl:comment>
    </xsl:if>  
    <xsl:for-each select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl">
        <xsl:element name="mapping">
          <xsl:if test="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:old">
            <xsl:attribute name="old">
              <xsl:value-of select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:old"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:if test="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:new">
            <xsl:attribute name="new">
              <xsl:value-of select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:new"/>
            </xsl:attribute>
          </xsl:if>
          <xsl:if test="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:dateAdded">
            <xsl:attribute name="dateAdded">
              <xsl:value-of select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:dateAdded"/>
            </xsl:attribute>
          </xsl:if>
        </xsl:element>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

En XSLT anterior Soy capaz de obtener el bucle de datos también va correcta, pero los datos que se han advenimiento es igual, yo bucle media está funcionando correctamente, pero el valor de nodo es el mismo

Para sugerir!

¿Fue útil?

Solución

Esta hoja de estilo:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ns="uuid:922EEC29-2DE3-4BA1-A46A-A300CB8FA85F"
 xmlns:tcm="http://www.tridion.com/ContentManager/5.0"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="ns tcm msxsl">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kVanityByComment" match="ns:VanityUrl" use="ns:comments"/>
    <xsl:template match="/">
        <xsl:variable name="vSourcesRTF">
            <xsl:copy-of select="document(tcm:ListItems/tcm:Item/@ID)"/>
        </xsl:variable>
        <mappings>
            <xsl:apply-templates select="msxsl:node-set($vSourcesRTF)/node()"/>
        </mappings>
    </xsl:template>
    <xsl:template match="ns:VanityUrl"/>
    <xsl:template match="ns:VanityUrl[generate-id()=
                                      generate-id(key('kVanityByComment',
                                                      ns:comments)[1])]">
        <xsl:comment>
            <xsl:value-of select="ns:comments"/>
        </xsl:comment>
        <xsl:apply-templates select="key('kVanityByComment',
                                         ns:comments)"
                             mode="output"/>
    </xsl:template>
    <xsl:template match="ns:VanityUrl" mode="output">
        <mapping>
            <xsl:apply-templates/>
        </mapping>
    </xsl:template>
    <xsl:template match="ns:VanityUrl/ns:comments" priority="1"/>
    <xsl:template match="ns:VanityUrl/*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Con esta entrada:

<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0" ID="tcm:232-83752-2" Managed="10682">
  <tcm:Item ID="229-564598" Title="010 News Mapping"/>
  <tcm:Item ID="229-564598" Title="020 CUGOs"/>
  <tcm:Item ID="229-564598" Title="030 Reserved Urls"/>
</tcm:ListItems>

Y esta fuente externa con 229-564598 URI:

<tcm:Component ID="tcm:229-564598" IsEditable="false" xmlns:tcm="http://www.tridion.com/ContentManager/5.0" xmlns:xlink="http://www.w3.org/1999/xlink">
  <tcm:Data>
    <tcm:Content>
      <MappingCollection xmlns="uuid:922EEC29-2DE3-4BA1-A46A-A300CB8FA85F">
        <VanityUrl>
          <old>mbp</old>
          <new>/SessionHandler.aspx?pageurl=/BP.aspx&amp;pub=/english&amp;section=IBE&amp;j=f</new>
          <dateAdded>2010-05-03T14:45:00</dateAdded>
          <comments> News mapping </comments>
        </VanityUrl>
        <VanityUrl>
          <old>about/news</old>
          <new>about/news/news.aspx</new>
          <dateAdded>2010-05-03T14:45:00</dateAdded>
          <comments> News mapping </comments>
        </VanityUrl>
      </MappingCollection>
    </tcm:Content>
  </tcm:Data>
</tcm:Component>

Salida:

<mappings>
    <!-- News mapping -->
    <mapping old="mbp" 
             new="/SessionHandler.aspx?pageurl=/BP.aspx&amp;pub=/english&amp;section=IBE&amp;j=f"
             dateAdded="2010-05-03T14:45:00"></mapping>
    <mapping old="about/news"
             new="about/news/news.aspx"
             dateAdded="2010-05-03T14:45:00"></mapping>
</mappings>

editar :. Múltiples fuentes de entrada

Otros consejos

Sí, el cambio realizado es, en efecto crítico. : -)

Lo que el para-cada bucle que hace es seleccionar cada elemento <em:VanityUrl> adecuados para su expresión XPath, que ese elemento del nodo de contexto para lo que está dentro de la for-each (llamado plantilla a pesar de que no es un <xsl:template> ) y, a continuación instantiate esa plantilla interior con el nuevo nodo de contexto.

Cuando se seguían usando "$ doc / ..." dentro de la para-cada bucle, estabas tirando de distancia del nodo de contexto, por lo que el para-cada uno estaba teniendo ningún efecto (excepto para repetir n veces).

Sus declaraciones <xsl:if test="$doc/..."> estaban evaluando si había cualquier nodo en todo el documento en lugar de bajo el elemento de contexto <em:VanityUrl>.

La declaración <xsl:value-of> presta atención a sólo el primer nodo del conjunto de nodos seleccionados, por lo que siempre estaba recibiendo el valor de la primero <em:VanityUrl>, independientemente del nodo de contexto.

Cuando comenzó la selección y prueba en relación con el nodo de contexto:

    <xsl:if test="em:old">

todo lo que llegó a ser mejor. : -)

Usted pidió información valiosa. Por razones estilísticas, es posible que desee reemplazar sus pruebas <xsl:if> con <xsl:apply-templates>. (Para una cosa que va a hacer @Dimitre Novatchev feliz. :-) Así

<xsl:if test="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments">
  <xsl:comment>
    <xsl:value-of select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments"/>
  </xsl:comment>
</xsl:if>

se convierte

<xsl:apply-templates select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments" />

y luego se necesita una plantilla separada para aquellos que:

<xsl:template match="em:comments">
  <xsl:comment>
    <xsl:value-of select="."/>
  </xsl:comment>
</xsl:template>

Hay varias ventajas a hacer eso. El mayor es que usted no tiene que duplicar esa expresión XPath de largo, que era propenso a errores si la expresión cada vez tenía que ser modificada. Si no hay em: Elementos de comentario, la aplica-plantillas no van a hacer nada, así que no emitirá un comentario

.

También modulariza su hoja de estilos, por lo que puede modificar la forma en em: se prestan los comentarios, por separado de dondequiera que se produzcan. Eso puede no importar demasiado en documentos XML muy simples donde Em: los comentarios se produce en un solo lugar, pero es el estilo que tiene mayor ventaja del poder de XSLT. También tenga en cuenta que esta versión modificada de salida voluntad múltiples comentarios, si hay varios em: comentarios, que su versión no. Una vez más es probable que no tiene múltiplos en la entrada, por lo que puede no importar.

Del mismo modo para los atributos de salida:

    <xsl:if test="em:old">
      <xsl:attribute name="old">
        <xsl:value-of select="em:old"/>
      </xsl:attribute>
    </xsl:if>

puede convertirse

    <xsl:apply-templates select="em:old[1]" />

con una plantilla separada

<xsl:template match="em:old">
   <xsl:attribute name="old">
     <xsl:value-of select="."/>
   </xsl:attribute>
</xsl:template>

Tenga en cuenta el [1], lo que evita el intento de múltiples atributos old="..." de salida para el mismo elemento si la entrada em: VanityUrl tiene múltiples em: elementos antiguos. Eso sería causa de su hoja de estilo para elevar un error. Pero tal vez usted que desee para generar un error en ese caso. Si es así, es probable que ya validar el código XML de entrada.

De hecho, se puede generalizar los apply-templates y la plantilla aquí para aplicar a los tres atributos:

    <xsl:apply-templates select="em:old[1] | em:new[1] | em:dateAdded[1]" />

Una vez más, si alguno de estos elementos no están presentes, no se hará nada para ellos (no se producirá ningún atributo vacío). La plantilla:

<xsl:template match="em:old | em:new | em:dateAdded">
   <xsl:attribute name="{local-name()}">
     <xsl:value-of select="."/>
   </xsl:attribute>
</xsl:template>

local-name() nos da el nombre del elemento, sin el prefijo de espacio de nombres.

Actualización:

Otra forma de asa que sería el uso de un modo:

    <xsl:apply-templates select="em:old[1] | em:new[1] | em:dateAdded[1]"
      mode="make-attribute" />

<xsl:template match="em:*" mode="make-attribute">
   <xsl:attribute name="{local-name()}">
     <xsl:value-of select="."/>
   </xsl:attribute>
</xsl:template>

A continuación, la plantilla de maquillaje atributo puede ser utilizado desde cualquier lugar, y el patrón de comparación no tiene que ser actualizado para que coincida con todos los elementos posibles es posible que desee hacer un atributo.

La única otra cosa que puedo decir es que el uso de espacios de nombres anterior es confuso ... para que no funcione como está. P.ej. su hoja de estilos utiliza esta URI de espacio para elementos como VanityURL:

 "http://www.espire.com/tridion/schemas"

pero el segundo documento de entrada utiliza este espacio de nombres URI para aquellos elementos:

 "uuid:922EEC29-2DE3-4BA1-A46A-A300CB8FA85F"

No importa que los prefijos de espacio de nombres son diferentes ( "em:" default vs), pero los URI de espacio de nombres tiene que coincidir. Supongo Vanidadespacio de nombres de URL URI debe haber cambiado, o de lo contrario su hoja de estilos no funcionaría ...

HTH!

Puede probar esto también !!

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tcm="http://www.tridion.com/ContentManager/5.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:em="http://www.espire.com/tridion/schemas" xmlns:tcmse="http://www.tridion.com/ContentManager/5.1/TcmScriptAssistant" exclude-result-prefixes="em xlink tcmse tcm">
  <xsl:output method="xml" version="1.0" encoding="UTF-16" indent="yes"/>     
  <!-- root match-->
  <xsl:template match="tcm:ListItems">
    <mappings>
      <xsl:apply-templates select="tcm:Item"/>
    </mappings>
  </xsl:template>
  <xsl:template match="tcm:Item">
    <xsl:variable name="doc" select="document(@ID)"/>
    <xsl:if test="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments">
      <xsl:comment>
        <xsl:value-of select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl/em:comments"/>
      </xsl:comment>
    </xsl:if>
    <xsl:for-each select="$doc/tcm:Component/tcm:Data/tcm:Content/em:MappingCollection/em:VanityUrl">
      <xsl:element name="mapping">
        <xsl:if test="em:old">
          <xsl:attribute name="old">
            <xsl:value-of select="em:old"/>
          </xsl:attribute>
        </xsl:if>
        <xsl:if test="em:new">
          <xsl:attribute name="new">
            <xsl:value-of select="em:new"/>
          </xsl:attribute>
        </xsl:if>
        <xsl:if test="em:dateAdded">
          <xsl:attribute name="dateAdded">
            <xsl:value-of select="em:dateAdded"/>
          </xsl:attribute>
        </xsl:if>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top