2012-08-24 7 views
5

In questo esempio di codice ho 2 sfide uno è impostare il nodo B1 dopo il nodo B e prima dei nodi C, D ed E e la seconda sfida è Aggiungi il secondo nodo KEY alla struttura/ROOT/E/OTHER/DEAL/KEYS.Come applicare più definizioni di modello in cui ognuna di esse sta cambiando la stessa struttura XML

Questo XML di esempio:

 <ROOT> 
      <A>some A text</A> 
      <B>some B text</B> 
      <C>some C text</C> 
      <D>some D text</D> 
      <E> 
      <OTHER> 
       <DEAL> 
       <KEYS> 
        <KEY> 
        <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType> 
        <KeyValue>123456|1</KeyValue> 
        </KEY> 
       </KEYS> 
       </DEAL> 
      </OTHER> 
      </E> 
     </ROOT> 

dopo la trasformazione:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <xsl:strip-space elements="*"/> 
     <xsl:output method="xml" indent="yes"/> 

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

     <!-- Identifiers are added by the system. Need to pass parms from the calling program --> 
     <xsl:template match="ROOT" name="add-B1"> 
      <xsl:variable name="elements-after" select="C|D|E"/> 
      <xsl:copy> 
       <xsl:copy-of select="* except $elements-after"/> 
       <B1>some B1 text</B1> 
       <xsl:copy-of select="$elements-after"/> 
      </xsl:copy> 
     </xsl:template> 

     <!-- KEY is added by the system. Need to pass parms from the calling program --> 
     <xsl:template match="ROOT/E/OTHER/DEAL/KEYS" name="add-KEYS"> 
      <xsl:param name="KeyIdentifierTypeB">654321|1</xsl:param> 
      <xsl:copy> 
       <xsl:copy-of select="*"/> 
       <KEY> 
        <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType> 
        <KeyValue> 
         <xsl:value-of select="$KeyIdentifierTypeB"/> 
        </KeyValue> 
       </KEY> 
      </xsl:copy> 
     </xsl:template> 
    </xsl:stylesheet> 

diventano:

 <?xml version="1.0" encoding="UTF-8"?> 
     <ROOT> 
      <A>some A text</A> 
      <B>some B text</B> 
      <B1 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">some B1 text</B1> 
      <C>some C text</C> 
      <D>some D text</D> 
      <E> 
       <OTHER> 
        <DEAL> 
         <KEYS> 
          <KEY> 
           <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType> 
           <KeyValue>123456|1</KeyValue> 
          </KEY> 
         </KEYS> 
        </DEAL> 
       </OTHER> 
      </E> 
     </ROOT> 

il motivo per cui la seconda definizione modello è stato completamente ignorato?

Il primo blocco del codice è stato risolto. Il nodo B1 viene impostato dopo il nodo B e prima del nodo C, D ed E o nelle altre parole viene impostato il nodo B1 e i nodi che devono essere posti dopo: C, D ed E
Il secondo modello = "ROOT/E/OTHER/DEAL/KEYS" che dovrebbe soddisfare la seconda parte della sfida: aggiungere il secondo nodo KEY alla struttura/ROOT/E/OTHER/DEAL/KEYS, è stato ignorato completamente. In aggiunta a questo fatto, se si commenta la prima corrispondenza del modello sul nodo ROOT, la seconda corrispondenza del modello = "ROOT/E/OTHER/DEAL/KEYS" funzionerà correttamente, in realtà aggiungerà la chiave aggiuntiva, ma io so perché il primo modello coincide sempre con il secondo. Provo xsl: template match = "ROOT/E/OTHER/DEAL/KEYS ... e xsl: for-each select = ... e xsl: call-template name =" add-KEYS "ma nulla mi ha aiutato

In realtà comprendo che i modelli di applicazione corrispondono a modelli di nodi con una struttura superiore con priorità più alta. La modifica della posizione del modello nel file XSLT non avrà alcun impatto, non la leggerà nell'esatta sequenza di righe, lo processerà abbinando la priorità "apply-templates" per ogni template corrispondente avrà apportato una modifica alla struttura XML, implicitamente farà il "for-each" per noi, ma non so come "consigli" il secondo modello che la struttura è stata modificata, e perché dovrei farlo, perché la seconda corrispondenza del modello è alla ricerca di una diversa posizione XPath, che btw non è mai stata toccata dal primo modello. nel mio caso? ... e qual è la migliore pratica come farlo?

Risultato atteso:

 <?xml version="1.0" encoding="UTF-8"?> 
     <ROOT> 
      <A>some A text</A> 
      <B>some B text</B> 
      <B1>some B1 text</B1> 
      <C>some C text</C> 
      <D>some D text</D> 
      <E> 
       <OTHER> 
        <DEAL> 
         <KEYS> 
          <KEY> 
           <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType> 
           <KeyValue>123456|1</KeyValue> 
          </KEY> 
          <KEY> 
           <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType> 
           <KeyValue>654321|1</KeyValue> 
          </KEY> 
         </KEYS> 
        </DEAL> 
       </OTHER> 
      </E> 
     </ROOT> 

risposta

3

Il secondo modello match="ROOT/E/OTHER/DEAL/KEYS" che dovrebbe soddisfare la seconda parte sfida: Aggiungere il secondo nodo chiave della struttura di /ROOT/E/OTHER/DEAL/KEYS, è stato ignorato completamente.

Il problema è che nel modello corrispondente a ROOT non c'è alcun xsl:apply-templates. Un modello viene selezionato per l'esecuzione solo nel risultato di un'istruzione xsl:apply-templates. Nel tuo codice non c'è alcun xsl:apply-templates, quindi il processore XSLT non applica più i modelli e termina l'esecuzione.

Sarebbe diverso se si sostituisse xsl:copy-of con xsl:apply-templates.

Ecco come fare:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="/*"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|B/preceding-sibling::node()"/> 
    <xsl:apply-templates select="B"/> 
    <B1>some B1 text</B1> 
    <xsl:apply-templates select="B/following-sibling::node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="KEY"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    <KEY> 
    <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType> 
    <KeyValue> 
    <xsl:value-of select="'654321|1'"/> 
    </KeyValue> 
    </KEY> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

Quando questa trasformazione viene applicata sul documento XML fornito:

<ROOT> 
    <A>some A text</A> 
    <B>some B text</B> 
    <C>some C text</C> 
    <D>some D text</D> 
    <E> 
     <OTHER> 
      <DEAL> 
       <KEYS> 
        <KEY> 
         <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType> 
         <KeyValue>123456|1</KeyValue> 
        </KEY> 
       </KEYS> 
      </DEAL> 
     </OTHER> 
    </E> 
</ROOT> 

The Wanted, risultato corretto viene prodotto:

<ROOT> 
    <A>some A text</A> 
    <B>some B text</B> 
    <B1>some B1 text</B1> 
    <C>some C text</C> 
    <D>some D text</D> 
    <E> 
     <OTHER> 
     <DEAL> 
      <KEYS> 
       <KEY> 
        <KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType> 
        <KeyValue>123456|1</KeyValue> 
        <KEY> 
        <KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType> 
        <KeyValue>654321|1</KeyValue> 
        </KEY> 
       </KEY> 
      </KEYS> 
     </DEAL> 
     </OTHER> 
    </E> 
</ROOT> 
+0

Grazie mille! –

+0

@ user1619586, prego. –

Problemi correlati