2010-01-22 4 views
4

J'ai un document XML, quelque chose commeXSLT multiples remplacement

<root> 
    <item>_x0034_SOME TEXT</item> 
    <item>SOME_x0020_TEXT</item> 
    <item>SOME_x0020_TEXT_x0032_</item> 
</root> 

Je l'exporter au format HTML, mais j'ai des problèmes remplaçant des caractères d'échappement. J'ai trouvé plusieurs modèles dans le Web pour faire remplacer du texte mais ils sont similaires à tout cela:

<xsl:template name="replaceString"> 
    <xsl:param name="strOrig"/> 
    <xsl:param name="strSearch"/> 
    <xsl:param name="strReplace"/> 
    <xsl:choose> 
     <xsl:when test="contains($strOrig, $strSearch)"> 
      <xsl:value-of select="substring-before($strOrig, $strSearch)"/> 
      <xsl:value-of select="$strReplace"/> 
      <xsl:call-template name="replaceString"> 
       <xsl:with-param name="strOrig" select="substring-after($strOrig, $strSearch)"/> 
       <xsl:with-param name="strSearch" select="$strSearch"/> 
       <xsl:with-param name="strReplace" select="$strReplace"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$strOrig"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

Je ne sais pas comment je peux l'utiliser pour faire les remplacements multiples. Je l'ai essayé:

<xsl:for-each select="PinnacleSys.PMC.Plugins.PVR.PvrChannelDescriptorWrapper/PinnacleSys.PMC.Plugins.PVR.DVBTPvrChannelDescriptor"> 

    <!--name="<xsl:value-of select="replace(replace(Name, '_x0020_', ' '), '_x0034_', '3')"/>" --> 
    <!--name="<xsl:value-of select="Name"/>"--> 
    <xsl:variable name="var1" select="Text" /> 
     <xsl:value-of select="replace($FeatureInfo,'Feature=','TESTING')"/> 

    name=" 
     <xsl:call-template name="replaceString"> 
      <xsl:with-param name="strOrig" select="Name"/> 
      <xsl:with-param name="strSearch" select="'_x0020_'"/> 
      <xsl:with-param name="strReplace" select="' '"/> 
     </xsl:call-template> 
     <xsl:call-template name="replaceString"> 
      <xsl:with-param name="strOrig" select="Name"/> 
      <xsl:with-param name="strSearch" select="'_x0030_'"/> 
      <xsl:with-param name="strReplace" select="'0'"/> 
     </xsl:call-template> 
     ..." 

Mais cette concatène juste la chaîne à plusieurs reprises, chacune avec un remplacement différent. J'ai également étudié des variables; si je pouvais assigner le résultat d'un appel de gabarit à une variable, je pourrais obtenir une solution sale, mais suffisante pour moi. Cependant je n'ai pas pu et je ne sais pas si c'est possible.

Quelle est la meilleure façon de le faire?

Je suis limité à 1.0 XSLT (avec 2.0 je pourrais appeler un remplacer() dans un autre).

+0

Quel analyseur utilisez-vous? msxml, .net? –

+0

Pour l'instant, j'utilise IE8.0, donc msxml je suppose. – raven

Répondre

5

Pour une solution native XSLT 1.0 utilisant un modèle pour le remplacement, les remplacements individuels doivent être imbriqués, comme illustré ici. Ceci n'est évidemment pas efficace en raison du nombre potentiel de remplacements. Une version optimisée est donnée ci-dessous.

<xsl:template match="item"> 
<xsl:copy> 
    <xsl:call-template name="replace-substring"> 
     <xsl:with-param name="original"> 
      <xsl:call-template name="replace-substring"> 
       <xsl:with-param name="original"> 
        <xsl:call-template name="replace-substring"> 
         <xsl:with-param name="original" select="."/> 
         <xsl:with-param name="substring" select="'_x0020_'"/> 
         <xsl:with-param name="replacement" select="' '"/> 
        </xsl:call-template> 
       </xsl:with-param> 
       <xsl:with-param name="substring" select="'_x0032_'"/> 
       <xsl:with-param name="replacement" select="'2'"/> 
      </xsl:call-template> 
     </xsl:with-param> 
     <xsl:with-param name="substring" select="'_x0034_'"/> 
     <xsl:with-param name="replacement" select="'4'"/> 
    </xsl:call-template> 
</xsl:copy> 
</xsl:template> 

<xsl:template name="replace-substring"> 
<xsl:param name="original"/> 
<xsl:param name="substring"/> 
<xsl:param name="replacement" select="''"/> 
<xsl:choose> 
    <xsl:when test="contains($original, $substring)"> 
     <xsl:value-of select="substring-before($original, $substring)"/> 
     <xsl:copy-of select="$replacement"/> 
     <xsl:call-template name="replace-substring"> 
      <xsl:with-param name="original" select="substring-after($original, $substring)"/> 
      <xsl:with-param name="substring" select="$substring"/> 
      <xsl:with-param name="replacement" select="$replacement"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$original"/> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

Depuis la sortie est HTML (XML serait bien aussi), les chaînes _xNNNN_ peuvent être convertis en leurs références de caractères numériques hexadécimaux, par exemple, &#xNNNN;. Ce modèle est efficace.

<xsl:template match="item"> 
<xsl:copy> 
    <xsl:call-template name="replaceChars"> 
     <xsl:with-param name="original" select="."/> 
    </xsl:call-template> 
</xsl:copy> 
</xsl:template> 

<xsl:template name="replaceChars"> 
<xsl:param name="original"/> 
<xsl:choose> 
    <xsl:when test="contains($original, '_x')"> 
     <xsl:value-of select="substring-before($original, '_x')"/> 
     <xsl:variable name="after" select="substring-after($original, '_x')"/> 
     <xsl:variable name="char" select="substring-before($after, '_')"/> 
     <xsl:value-of select="concat('&amp;#x',$char,';')" disable-output-escaping="yes"/> 
     <xsl:call-template name="replaceChars"> 
      <xsl:with-param name="original" select="substring-after($after, '_')"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$original"/> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

Ceci est la sortie résultante.

<root> 
    <item>&#x0034;SOME TEXT</item> 
    <item>SOME&#x0020;TEXT</item> 
    <item>SOME&#x0020;TEXT&#x0032;</item> 
</root> 
+0

Merci, cela a vraiment fait l'affaire. – raven

+0

De rien. –

1

XSLT 1.0 n'est pas le meilleur au remplacement de chaîne. Le modèle que vous avez serait celui à utiliser. Cependant, pour les remplacements de chaînes, j'utilise une chaîne de remplacement dans une autre langue, généralement JavaScript ou C#/VB.NET (Java ou tout autre langage fonctionnerait aussi). Vraisemblablement, à un certain point, le document XML est sérialisé en une chaîne. Une fois que c'est une chaîne, utilisez une simple chaîne de caractères pour remplacer une chaîne ou des expressions régulières pour une correspondance de modèle plus complexe.

+0

Comme je viens de le dire là-haut, j'utilise les capacités d'analyse IE8, pour éviter la programmation. Je n'essaierai donc pas si je trouve une solution XSLT native. Mais merci. – raven

+0

Une solution XSLT native est donnée dans ma réponse ultérieure. –

1

Placez l'appel du modèle à l'intérieur du corps variable.

<xsl:variable name="myVar"><xsl:call-template name="replaceString"> 
     <xsl:with-param name="strOrig" select="Name"/> 
     <xsl:with-param name="strSearch" select="'_x0020_'"/> 
     <xsl:with-param name="strReplace" select="' '"/> 
    </xsl:call-template> 
</xsl:variable> 

Ceci attribue à myVar le contenu de l'appel.

+0

@Jaime Pardos vous êtes les bienvenus – Dewfy

1

Jetez un coup d'œil au support des expressions régulières dans EXSLT (www.exslt.org). Le support EXSLT est disponible dans la plupart des processeurs XSL modernes.