2012-08-24 11 views
5

W tym przykładzie kodu mam 2 wyzwania, jednym jest ustawienie węzła B1 po węźle B i przed węzłem C, D i E, a drugim wyzwaniem jest Dodaj drugi węzeł KEY do struktury/ROOT/E/OTHER/DEAL/KEYS.Jak zastosować wiele definicji szablonów, w których każdy z nich zmienia tę samą strukturę XML

Próbka XML:

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

po transformacji:

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

stać:

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

dlaczego druga definicja szablon został całkowicie zignorowany?

Pierwsza uczelnia kodów została rozstrzygnięta Węzeł B1 jest ustawiona po węźle B, a przed węzłem C, D i E lub innymi słowy węzeł B1 i węzły, które muszą być miejscami po: C, D i E
Drugi szablon dopasowania = "ROOT/E/OTHER/DEAL/KEYS", który powinien spełniać drugą część wyzwania: dodanie drugiego węzła KEY do struktury/ROOT/E/OTHER/DEAL/KEYS zostało zignorowane całkowicie. Oprócz tego, jeśli skomentujesz pierwszy szablon dopasowania w węźle ROOT, drugi szablon dopasowania = "ROOT/E/OTHER/DEAL/KEYS" będzie działał poprawnie, to faktycznie doda dodatkowy klucz, ale ja don wiesz, dlaczego pierwsze dopasowanie szablonu zawsze zastępuje drugie. Próbuję xsl: template match = "ROOT/E/OTHER/DEAL/KEYS ... i xsl: for-each select = ... i xsl: call-template name =" add-KEYS "ale nic mi nie pomogło obecnie:

Rzeczywiście rozumiem, że szablony zastosowań, dopasowują szablony węzłów o wyższej strukturze z najwyższym priorytetem. Zmiana miejsca szablonu w pliku XSLT nie będzie miała żadnego wpływu, nie będzie czytać go w dokładnej sekwencji linii, zamiast tego przetworzy je, dopasowując priorytet. "Zastosuj szablony" dla każdego pasującego szablonu dokona zmiany w strukturze XML, domyślnie zrobi to "dla każdego" dla nas, ale nie wiem jak "doradzić" drugi szablon, w którym struktura została zmieniona, i dlaczego powinienem to zrobić, ponieważ drugie dopasowanie do szablonu szuka innej lokalizacji XPath, która nigdy nie została dotknięta z pierwszego szablonu. Czy powinienem zastosować szablon sekwencyjny? g w moim przypadku? ... i jaka jest najlepsza praktyka, jak to zrobić?

Oczekiwany wynik:

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

Odpowiedz

3

Drugi szablon match="ROOT/E/OTHER/DEAL/KEYS" które powinny zadowolić drugą część wyzwanie: Dodanie drugiego węzła Klucz do struktury /ROOT/E/OTHER/DEAL/KEYS został całkowicie zignorowany.

Problem polega na tym, że w szablonie pasującym do ROOT nie ma żadnego xsl:apply-templates. Szablon zostanie wybrany tylko do wykonania w wyniku instrukcji xsl:apply-templates. W twoim kodzie nie ma żadnego xsl:apply-templates, dlatego procesor XSLT nie stosuje już szablonów i kończy wykonywanie.

Byłoby inaczej, gdyby wymienić xsl:copy-of na xsl:apply-templates.

Oto jak to zrobić:

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

Kiedy transformacja ta jest stosowana na dostarczonych dokumentów XML:

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

poszukiwany, poprawny wynik jest produkowany:

<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

Dziękuję bardzo! –

+0

@ user1619586, Nie ma za co. –

Powiązane problemy