Domanda

Sto usando XSLT e XML.

Per prima cosa lavorerò su due xml.

Primo 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>

IL Secondo XML lo otterremo utilizzando l'ID sopra, ad es.tcm:232-564598 ecc., di seguito è riportato uno degli xml per l'ID tcm:232-564598 e gli altri ID avranno lo stesso tipo di 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>

Sto cercando di ottenere il formato XML inferiore utilizzando entrambi gli XML sopra.

<?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> 

Ed ecco il mio XSLT in cui sto cercando di generare il formato XML sopra ma non funziona per me.tieni presente che il primo xml è l'xml primario che verrà trasformato utilizzando XSLT di seguito

<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>

In xslt sopra sono in grado di ottenere che anche il ciclo di dati funzioni correttamente, ma i dati che arrivano sono gli stessi, intendo che il ciclo funziona correttamente, ma il valore del nodo è lo stesso

Per favore suggerisci!

È stato utile?

Soluzione

Questo foglio di stile:

<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 questo ingresso:

<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>

E questa fonte esterna 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>

Output:

<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>

Modifica :. Multiple sorgenti di ingresso

Altri suggerimenti

Sì, il cambiamento che hai apportato è davvero fondamentale.:-)

Ciò che fa il ciclo for-each è selezionarli ciascuno <em:VanityUrl> elemento che corrisponde alla tua espressione XPath, rendi quell'elemento il nodo di contesto per ciò che è all'interno di for-each (chiamato the modello anche se non è un <xsl:template>), quindi creare un'istanza del modello interno con il nuovo nodo di contesto.

Quando continuavi a utilizzare "$doc/..." all'interno del ciclo for-each, stavi eliminando il nodo di contesto, quindi for-each non aveva alcun effetto (tranne che per ripetere n volte).

Tuo <xsl:if test="$doc/..."> le dichiarazioni stavano valutando se esistesse un nodo del genere nell'intero documento invece che sotto l'elemento contesto <em:VanityUrl>.

IL <xsl:value-of> presta attenzione solo al primo nodo nel set di nodi selezionato, quindi ottieni sempre il valore da Primo <em:VanityUrl>, indipendentemente dal nodo del contesto.

Quando hai iniziato a selezionare e testare rispetto al nodo di contesto:

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

tutto è diventato migliore.:-)

Hai chiesto un contributo prezioso.Per ragioni stilistiche, potresti voler sostituire il tuo <xsl:if> prove con <xsl:apply-templates>.(Per prima cosa renderai felice @Dimitre Novatchev.:-) COSÌ

<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>

diventa

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

e quindi hai bisogno di un modello separato per quelli:

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

Ci sono diversi vantaggi nel farlo.Il più grande è che non è necessario duplicare quella lunga espressione XPath, che era soggetta a errori se l'espressione avesse mai avuto bisogno di essere modificata.Se non ci sono elementi em:comment, i modelli apply-template non faranno nulla, quindi non emetteranno un commento.

Inoltre modularizza il tuo foglio di stile, in modo che tu possa modificare il modo in cui vengono visualizzati em:comments, separatamente da dove possono verificarsi.Ciò potrebbe non avere molta importanza nei documenti XML semplici in cui em:comments si trova in un solo posto, ma è lo stile che sfrutta al meglio la potenza di XSLT.Tieni inoltre presente che questa versione modificata genererà più commenti se sono presenti più em:commenti, cosa che la tua versione non farà.Ancora una volta probabilmente non hai multipli nell'input, quindi potrebbe non avere importanza.

Allo stesso modo per gli attributi di output:

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

può diventare

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

con un modello separato

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

Notare la [1], che evita di tentare di generare output multipli old="..." attributi per lo stesso elemento se l'input em:VanityUrl ha più elementi em:old.Ciò causerebbe un errore nel tuo foglio di stile.Ma forse tu Volere per sollevare un errore in quel caso.Se è così, probabilmente stai già convalidando il tuo XML di input.

In effetti, puoi generalizzare qui apply-templates e template per applicarli a tutti e tre gli attributi:

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

Ancora una volta, se uno qualsiasi di questi elementi non è presente, non verrà fatto nulla per esso (non verrà prodotto alcun attributo vuoto).Il template:

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

local-name() ci dà il nome dell'elemento, senza il prefisso dello spazio dei nomi.

Aggiornamento:

Un altro modo per gestirlo sarebbe utilizzare una modalità:

    <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>

Quindi il tuo modello di attributo può essere utilizzato da qualsiasi luogo e il modello di corrispondenza non deve essere aggiornato per corrispondere a ogni possibile elemento da cui potresti voler creare un attributo.

L'unica altra cosa che vorrei dire è che l'uso degli spazi dei nomi sopra è fonte di confusione... non dovrebbe funzionare così com'è.Per esempio.il tuo foglio di stile utilizza questo URI dello spazio dei nomi per elementi come VanityURL:

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

ma il secondo documento di input utilizza questo URI dello spazio dei nomi per quegli elementi:

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

Non importa che i prefissi dello spazio dei nomi siano diversi ("em:" vs.default), ma gli URI dello spazio dei nomi devono corrispondere.Immagino che l'URI dello spazio dei nomi di VanityURL debba essere cambiato, altrimenti il ​​tuo foglio di stile non funzionerebbe...

HTH!

Si può provare anche questo !!

<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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top