2016-08-25 1 views
4

J'essaie de convertir le format texte Flash en texte basé sur HTML.Comment identifier un ensemble de noeuds et l'ajouter dans un autre où la structure de la source XML varie dans XSLT?

Il y a <LI></LI> blocs dans le fichier XML source. J'ai besoin d'ajouter un bloc adjacent <LI> dans un bloc <ul>.

<p></p> 
<li></li> ------ 
<li></li>  | - should be wrapped with <ul> tag 
<li></li> ------ 
<p></p> 
<li></li> 
<li></li> 
<li></li> 
<p></p> 

XML Source

<root> 
    <TEXTFORMAT LEADING="2"> 
     <P ALIGN="LEFT"> 
      edfg 
     </P> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <P ALIGN="LEFT"> 
      sdgfdsgsds 
     </P> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <LI> 
      sdfgdsg 
     </LI> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <LI> 
      dsgdfgdsfg 
     </LI> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <LI> 
      <FONT FACE="Lato" SIZE="12" COLOR="#4B4B4B" LETTERSPACING="0" KERNING="0">errytrtyr</FONT> 
     </LI> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <P ALIGN="LEFT"> 
      sdgfdsgsds 
     </P> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <LI> 
      <FONT FACE="System" SIZE="16" COLOR="#4B4B4B" LETTERSPACING="0" KERNING="0">nm,hjku 
       <FONT FACE="Lato" SIZE="12"></FONT> 
      </FONT> 
     </LI> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <LI> 
      <FONT FACE="System" SIZE="16" COLOR="#4B4B4B" LETTERSPACING="0" KERNING="0"> 
       <B>hgjgj</B> 
       <FONT FACE="Lato" SIZE="12"></FONT> 
      </FONT> 
     </LI> 
    </TEXTFORMAT> 
    <TEXTFORMAT LEADING="2"> 
     <P ALIGN="CENTER"> 
      <FONT FACE="Lato" SIZE="12" COLOR="#4B4B4B" LETTERSPACING="0" KERNING="0">centered text</FONT> 
     </P> 
    </TEXTFORMAT> 
</root> 

Sortie prévue

<div> 
    <div style="text-align:LEFT; "> 
     edfg 
    </div> 
    <div style="text-align:LEFT; "> 
     sdgfdsgsds 
    </div> 
    <ul> 
     <li> 
      sdfgdsg 
     </li> 
     <li> 
      dsgdfgdsfg 
     </li> 
     <li> 
      <FONT COLOR="#4B4B4B" FACE="Lato" SIZE="12">errytrtyr</FONT> 
     </li> 
    </ul> 
    <div style="text-align:LEFT; "> 
     sdgfdsgsds 
    </div> 
    <ul> 
     <li> 
      <FONT COLOR="#4B4B4B" FACE="System" SIZE="16">nm,hjku 
       <FONT FACE="Lato" SIZE="12"></FONT> 
      </FONT> 
     </li> 
     <li> 
      <FONT COLOR="#4B4B4B" FACE="System" SIZE="16"> 
       <B>hgjgj</B> 
       <FONT FACE="Lato" SIZE="12"></FONT> 
      </FONT> 
     </li> 
    </ul> 
    <div style="text-align:CENTER; "> 
     <FONT COLOR="#4B4B4B" FACE="Lato" SIZE="12">centered text</FONT> 
    </div> 
</div> 

Mon code:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes" method="html"/> 

    <!-- identity template --> 

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

    <xsl:template match="root"> 
     <div> 
      <xsl:apply-templates/> 
     </div> 
    </xsl:template> 

    <!-- remove unwanted attributes --> 
    <xsl:template match="@LETTERSPACING|@KERNING"/> 

    <!-- Remove <P> tag and set the alignment --> 
    <xsl:template match="P"> 
     <div> 
      <xsl:attribute name="style"> 
       <!-- collect attributes --> 
       <xsl:variable name="styles"> 
        <xsl:if test="@ALIGN"> 
         <xsl:value-of select="concat('text-align:', @ALIGN)"/> 
         <xsl:text>; </xsl:text> 
        </xsl:if> 
       </xsl:variable> 
       <!-- delete trailing spaces --> 
       <xsl:value-of select="$styles"/> 
      </xsl:attribute> 
      <xsl:apply-templates/> 
     </div> 
    </xsl:template> 

    <!-- Replace <LI> with <li> --> 
    <xsl:template match="LI"> 
     <li><xsl:apply-templates/></li> 
    </xsl:template> 

    <!-- Remove TEXTFORMAT --> 
    <xsl:template match="TEXTFORMAT"> 
     <xsl:apply-templates/> 
    </xsl:template> 

</xsl:stylesheet> 
+1

Très bonne question, BTW. Le code d'échantillon syntaxique, complet, syntaxiquement valide et -input, sortie attendue correspond à l'entrée donnée. Sur-point dans tous les domaines pertinents. – Tomalak

+0

@Tomalak pouvez-vous s'il vous plaît regarder [this] (http://stackoverflow.com/questions/39205509/how-do-you-move-an-attribute-in-the-first-child-of-a-parent- to-the-parent-in-xsl) Merci pour votre réponse exellent – tymspy

Répondre

1

la XSLT suivante 1.0 transformation vous donne ce qui semble être le résultat recherché:

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

    <xsl:key name="list" match="TEXTFORMAT[LI]" use="generate-id(
     (self::*|preceding-sibling::*)[LI][ 
      not(preceding-sibling::*[1][LI]) 
     ][last()] 
    )" /> 

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

    <xsl:template match="root"> 
     <div> 
      <xsl:apply-templates /> 
     </div> 
    </xsl:template> 

    <!-- Remove <P> tag and set the alignment --> 
    <xsl:template match="P"> 
     <div> 
      <xsl:attribute name="style"> 
       <xsl:apply-templates select="@*" mode="css" /> 
      </xsl:attribute> 
      <xsl:apply-templates/> 
     </div> 
    </xsl:template> 

    <xsl:template match="@ALIGN" mode="css"> 
     <xsl:value-of select="concat('text-align:', ., ';')"/> 
    </xsl:template> 
    <!-- add more --> 
    <xsl:template match="@*" mode="css" /> 

    <!-- remove unwanted attributes --> 
    <xsl:template match="@LETTERSPACING|@KERNING"/> 

    <xsl:template match="TEXTFORMAT[LI]"> 
     <xsl:variable name="adjacent" select="key('list', generate-id())" /> 
     <xsl:if test="$adjacent"> 
      <ul> 
       <xsl:apply-templates select="$adjacent/LI" /> 
      </ul> 
     </xsl:if> 
    </xsl:template> 

    <!-- Replace <LI> with <li> --> 
    <xsl:template match="LI"> 
     <li><xsl:apply-templates/></li> 
    </xsl:template> 

    <!-- Remove TEXTFORMAT --> 
    <xsl:template match="TEXTFORMAT"> 
     <xsl:apply-templates/> 
    </xsl:template> 

</xsl:stylesheet> 

résultat:

<div> 
    <div style="text-align:LEFT;"> 
     edfg 

    </div> 
    <div style="text-align:LEFT;"> 
     sdgfdsgsds 

    </div> 
    <ul> 
     <li> 
     sdfgdsg 

     </li> 
     <li> 
     dsgdfgdsfg 

     </li> 
     <li><FONT FACE="Lato" SIZE="12" COLOR="#4B4B4B">errytrtyr</FONT></li> 
    </ul> 
    <div style="text-align:LEFT;"> 
     sdgfdsgsds 

    </div> 
    <ul> 
     <li><FONT FACE="System" SIZE="16" COLOR="#4B4B4B">nm,hjku 
      <FONT FACE="Lato" SIZE="12"></FONT></FONT></li> 
     <li><FONT FACE="System" SIZE="16" COLOR="#4B4B4B"><B>hgjgj</B><FONT FACE="Lato" SIZE="12"></FONT></FONT></li> 
    </ul> 
    <div style="text-align:CENTER;"><FONT FACE="Lato" SIZE="12" COLOR="#4B4B4B">centered text</FONT></div> 
</div> 

La clé de la solution, littéralement, est cette construction:

<xsl:key name="list" match="TEXTFORMAT[LI]" use="generate-id(
    (self::*|preceding-sibling::*)[LI][ 
     not(preceding-sibling::*[1][LI]) 
    ][last()] 
)" /> 

Ce index chaque TEXTFORMAT[LI] dans le document par l'ID unique de l'TEXTFORMAT[LI] le plus proche qui a commencé la série en cours, à savoir la le plus proche qui n'a pas TEXTFORMAT[LI] avant.

Allant de là, nous pouvons décider de <xsl:template match="TEXTFORMAT[LI]"> si quelque chose de sortie ou non pour une donnée TEXTFORMAT[LI].

1

Ce type de regroupement est un peu difficile à faire dans XSLT 1.0.

Si on peut supposer que chaque groupe LI est précédé d'un P, et qu'il n'y a pas de nœuds d'un autre type dans l'élément root, alors vous pouvez faire:

XSLT 1.0

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

<xsl:key name="LI" match="TEXTFORMAT[LI]" use="generate-id(preceding-sibling::TEXTFORMAT[P][1])" /> 

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

<xsl:template match="root"> 
    <div> 
     <xsl:apply-templates select="TEXTFORMAT[P]"/> 
    </div> 
</xsl:template> 

<xsl:template match="TEXTFORMAT"> 
    <xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="P"> 
    <div style="text-align:{@ALIGN};"> 
     <xsl:apply-templates/> 
    </div> 
    <xsl:variable name="li" select="key('LI', generate-id(..))" /> 
    <xsl:if test="$li"> 
     <ul> 
      <xsl:apply-templates select="$li"/> 
     </ul>   
    </xsl:if> 
</xsl:template> 

<xsl:template match="LI"> 
    <li> 
     <xsl:apply-templates/> 
    </li> 
</xsl:template> 

<xsl:template match="@LETTERSPACING|@KERNING"/> 

</xsl:stylesheet>