2012-02-21 31 views
13

Tengo el siguiente xslt para transformar datos en un formato aceptado por JQuery. Sin embargo, como JSON no acepta comillas dobles en la cadena de datos, tengo que sustituir "con una secuencia de escape \"XSLT + Sustitución de comillas dobles con secuencia de escape

XML:

<?xml version="1.0" encoding="UTF-8"?> 
<Rowsets> 
    <Rowset> 
     <Columns> 
      <Column Description="Element_1" SQLDataType="12" /> 
      <Column Description="Element_2" SQLDataType="12" /> 
      <Column Description="Element_3" SQLDataType="93" /> 
     </Columns> 
     <Row> 
      <Element_1>test_data</Element_1> 
      <Element_2>test_quo"te</Element_2> 
      <Element_3>test_data</Element_3> 
     </Row> 
    </Rowset> 
</Rowsets> 

XSLT actual:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" exclude-result-prefixes="java"> 
    <xsl:output method="text" media-type="text/csv" encoding="UTF-8"/> 
    <xsl:param name="RowDelim">],</xsl:param> 
    <xsl:param name="RowLast">]</xsl:param> 
    <xsl:param name="RowStart">[</xsl:param> 
    <xsl:param name="startBracket">{ </xsl:param> 
    <xsl:param name="JQTableData">"aaData": [</xsl:param> 
    <xsl:param name="JQTableEnd">] }</xsl:param> 
    <xsl:param name="FieldDelim">,</xsl:param> 
    <xsl:param name="StringDelim">"</xsl:param> 
    <xsl:param name="DateFormat">yyyy-MM-dd HH:mm:ss</xsl:param> 


    <xsl:template match="/"> 





     <xsl:for-each select="Rowsets"> 

      <xsl:for-each select="Rowset"> 
      <xsl:value-of select="$startBracket"/> 
      <xsl:value-of select="$JQTableData"/> 
       <xsl:variable name="CurrentColumns" select="Columns"/> 
       <xsl:for-each select="Columns"> 
        <xsl:for-each select="Column"> 

         <xsl:if test="not(position() = last())"> 

         </xsl:if> 
        </xsl:for-each> 

       </xsl:for-each> 
       <xsl:for-each select="Row"> 
       <xsl:value-of select="$RowStart"/> 
        <xsl:for-each select="*"> 
         <xsl:variable name="ColName"> 
          <xsl:value-of select="name(.)"/> 
         </xsl:variable> 
         <xsl:variable name="ColType"> 
          <xsl:value-of select="$CurrentColumns/Column[@Name=$ColName]/@SQLDataType"/> 
         </xsl:variable> 
         <xsl:choose> 
          <xsl:when test="$ColType= '2' or $ColType= '3' or $ColType= '4' or $ColType= '5' or 

$ColType= '6' or $ColType= '7' or $ColType= '8' or $ColType= '-7'"> 
           <xsl:value-of select="."/> 
          </xsl:when> 
          <xsl:otherwise> 
           <xsl:value-of select="$StringDelim"/> 
           <xsl:choose> 
            <xsl:when test="$ColType= '91' or $ColType= '92' or $ColType= '93'"> 
             <xsl:choose> 
              <xsl:when test=". = 'TimeUnavailable'"> 
               <xsl:value-of select="."/> 
              </xsl:when> 
              <xsl:otherwise> 
                         </xsl:otherwise> 
             </xsl:choose> 
            </xsl:when> 
            <xsl:otherwise> 
            <xsl:choose> 
             <xsl:when test=". = 'true'"> 
              <xsl:text>Y</xsl:text> 
             </xsl:when> 
             <xsl:when test=". = 'false'"> 
              <xsl:text>N</xsl:text> 
             </xsl:when> 
             <xsl:otherwise> 
              <xsl:value-of select="."/> 
             </xsl:otherwise> 
             </xsl:choose> 
            </xsl:otherwise> 
           </xsl:choose> 
           <xsl:value-of select="$StringDelim"/> 
          </xsl:otherwise> 
         </xsl:choose> 
         <xsl:if test="not(position() = last())"> 
          <xsl:value-of select="$FieldDelim"/> 
         </xsl:if> 
        </xsl:for-each> 
          <xsl:if test="not(position() = last())"> 
          <xsl:value-of select="$RowDelim"/> 
         </xsl:if> 
          <xsl:if test="position() = last()"> 
          <xsl:value-of select="$RowLast"/> 
         </xsl:if> 

       </xsl:for-each> 
       <xsl:value-of select="$JQTableEnd"/> 
      </xsl:for-each> 
     </xsl:for-each> 
    </xsl:template> 



</xsl:stylesheet> 

salida de corriente:

{ "aaData": [["test_data","test_quo"te","test_data"]] } 

salida deseada:

{ "aaData": [["test_data","test_quo\"te","test_data"]] } 
+0

user1130511: ¿No es el carácter de escape '\' (back-slash)? –

+0

user1130511: El código XSLT proporcionado no está bien formado, nadie puede trabajar con él ahora. Por favor, edite la pregunta y corrija. –

+0

@DimitreNovatchev woops, copiado la versión incorrecta. He actualizado el XSLT, eso debería funcionar. Y sí, debería ser una barra diagonal – user1130511

Respuesta

26

Añadir esta plantilla para su código:

<xsl:template name="escapeQuote"> 
     <xsl:param name="pText" select="."/> 

     <xsl:if test="string-length($pText) >0"> 
     <xsl:value-of select= 
     "substring-before(concat($pText, '&quot;'), '&quot;')"/> 

     <xsl:if test="contains($pText, '&quot;')"> 
     <xsl:text>\"</xsl:text> 

     <xsl:call-template name="escapeQuote"> 
      <xsl:with-param name="pText" select= 
      "substring-after($pText, '&quot;')"/> 
     </xsl:call-template> 
     </xsl:if> 
     </xsl:if> 
    </xsl:template> 

Luego cambie:

<xsl:value-of select="."/> 

a:

<xsl:call-template name="escapeQuote"/> 

Su transformación completa se convierte ahora en:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" exclude-result-prefixes="java"> 
     <xsl:output method="text" media-type="text/csv" encoding="UTF-8"/> 
     <xsl:param name="RowDelim">],</xsl:param> 
     <xsl:param name="RowLast">]</xsl:param> 
     <xsl:param name="RowStart">[</xsl:param> 
     <xsl:param name="startBracket">{ </xsl:param> 
     <xsl:param name="JQTableData">"aaData": [</xsl:param> 
     <xsl:param name="JQTableEnd">] }</xsl:param> 
     <xsl:param name="FieldDelim">,</xsl:param> 
     <xsl:param name="StringDelim">"</xsl:param> 
     <xsl:param name="DateFormat">yyyy-MM-dd HH:mm:ss</xsl:param> 


     <xsl:template match="/"> 

      <xsl:for-each select="Rowsets"> 

       <xsl:for-each select="Rowset"> 
       <xsl:value-of select="$startBracket"/> 
       <xsl:value-of select="$JQTableData"/> 
        <xsl:variable name="CurrentColumns" select="Columns"/> 
        <xsl:for-each select="Columns"> 
         <xsl:for-each select="Column"> 

          <xsl:if test="not(position() = last())"> 

          </xsl:if> 
         </xsl:for-each> 

        </xsl:for-each> 
        <xsl:for-each select="Row"> 
        <xsl:value-of select="$RowStart"/> 
         <xsl:for-each select="*"> 
          <xsl:variable name="ColName"> 
           <xsl:value-of select="name(.)"/> 
          </xsl:variable> 
          <xsl:variable name="ColType"> 
           <xsl:value-of select="$CurrentColumns/Column[@Name=$ColName]/@SQLDataType"/> 
          </xsl:variable> 
          <xsl:choose> 
           <xsl:when test="$ColType= '2' or $ColType= '3' or $ColType= '4' or $ColType= '5' or 

    $ColType= '6' or $ColType= '7' or $ColType= '8' or $ColType= '-7'"> 
            <xsl:value-of select="."/> 
           </xsl:when> 
           <xsl:otherwise> 
            <xsl:value-of select="$StringDelim"/> 
            <xsl:choose> 
             <xsl:when test="$ColType= '91' or $ColType= '92' or $ColType= '93'"> 
              <xsl:choose> 
               <xsl:when test=". = 'TimeUnavailable'"> 
                <xsl:value-of select="."/> 
               </xsl:when> 
               <xsl:otherwise> 
                          </xsl:otherwise> 
              </xsl:choose> 
             </xsl:when> 
             <xsl:otherwise> 
             <xsl:choose> 
              <xsl:when test=". = 'true'"> 
               <xsl:text>Y</xsl:text> 
              </xsl:when> 
              <xsl:when test=". = 'false'"> 
               <xsl:text>N</xsl:text> 
              </xsl:when> 
              <xsl:otherwise> 
               <xsl:call-template name="escapeQuote"/> 
               <!-- <xsl:value-of select="."/> --> 
              </xsl:otherwise> 
              </xsl:choose> 
             </xsl:otherwise> 
            </xsl:choose> 
            <xsl:value-of select="$StringDelim"/> 
           </xsl:otherwise> 
          </xsl:choose> 
          <xsl:if test="not(position() = last())"> 
           <xsl:value-of select="$FieldDelim"/> 
          </xsl:if> 
         </xsl:for-each> 
           <xsl:if test="not(position() = last())"> 
           <xsl:value-of select="$RowDelim"/> 
          </xsl:if> 
           <xsl:if test="position() = last()"> 
           <xsl:value-of select="$RowLast"/> 
          </xsl:if> 

        </xsl:for-each> 
        <xsl:value-of select="$JQTableEnd"/> 
       </xsl:for-each> 
      </xsl:for-each> 
     </xsl:template> 

     <xsl:template name="escapeQuote"> 
      <xsl:param name="pText" select="."/> 

      <xsl:if test="string-length($pText) >0"> 
      <xsl:value-of select= 
      "substring-before(concat($pText, '&quot;'), '&quot;')"/> 

      <xsl:if test="contains($pText, '&quot;')"> 
      <xsl:text>\"</xsl:text> 

      <xsl:call-template name="escapeQuote"> 
       <xsl:with-param name="pText" select= 
       "substring-after($pText, '&quot;')"/> 
      </xsl:call-template> 
      </xsl:if> 
      </xsl:if> 
     </xsl:template> 

</xsl:stylesheet> 

cuando se aplica esta transformación en el documento XML proporcionado:

<Rowsets> 
    <Rowset> 
     <Columns> 
      <Column Description="Element_1" SQLDataType="12" /> 
      <Column Description="Element_2" SQLDataType="12" /> 
      <Column Description="Element_3" SQLDataType="93" /> 
     </Columns> 
     <Row> 
      <Element_1>test_data</Element_1> 
      <Element_2>test_quo"te</Element_2> 
      <Element_3>test_data</Element_3> 
     </Row> 
    </Rowset> 
</Rowsets> 

la deseada, el resultado correcto se produce:

{ "aaData": [["test_data","test_quo\"te","test_data"]] } 
+0

Lo siento, soy relativamente nuevo en XSLT. ¿Existe la posibilidad de aplicar automáticamente esta plantilla a todos los valores de, digamos un "cuerpo/fila" al agregar algún atributo? –

+1

@JamesCazzetta, se debe invocar una plantilla con nombre. Recomiendo encarecidamente que tome un curso de capacitación XSLT, como este: http://www.pluralsight.com/courses/xslt-foundations-part1 –

Cuestiones relacionadas