XSLT 1.0 หลีกเลี่ยงเครื่องหมายคำพูดคู่และแบ็กสแลชในสตริง

ฉันมีสตริงดังนี้และพยายามแปลงเป็นรูปแบบ json:

ทดสอบ "out" และ \new

ผลลัพธ์ที่คาดหวังคือ Test \"out\" และ \new

ฉันลองโดยเรียกเทมเพลตสำหรับ Escapequote - ทำงานได้ดีสำหรับเครื่องหมายคำพูด Escape:

<xsl:template name="escapeQuote">
    <xsl:param name="pText" select="concat(normalize-space(.), '')" />
    <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>

เทมเพลตสำหรับแบ็กสแลช Escape - ใช้งานได้กับแบ็กสแลชเท่านั้น:

<xsl:template name="jsonescape">
 <xsl:param name="str" select="."/>
  <xsl:choose>
    <xsl:when test="contains($str, '\')">
      <xsl:value-of select="concat(substring-before($str, '\'), '\\' )"/>
      <xsl:call-template name="jsonescape">
        <xsl:with-param name="str" select="substring-after($str, '\')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="$str"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

คำถามของฉันจะเรียกทั้งสองเทมเพลตหรือรวมได้อย่างไร โปรดช่วยฉันด้วย


person Srikanth Reddy    schedule 26.05.2016    source แหล่งที่มา
comment
เรียกเทมเพลตที่สองโดยให้ผลลัพธ์ของเทมเพลตแรกเป็นพารามิเตอร์อินพุต   -  person michael.hor257k    schedule 26.05.2016
comment
คุณช่วยแนะนำไวยากรณ์ให้ฉันหน่อยได้ไหม   -  person Srikanth Reddy    schedule 26.05.2016
comment
เนื่องจากฉันยังใหม่กับ xsl โปรดช่วยฉันในการส่งผลลัพธ์ของเทมเพลตไปยังเทมเพลตอื่น   -  person Srikanth Reddy    schedule 26.05.2016
comment
เนื่องจากทั้งสองเป็นเทมเพลตแบบเรียกซ้ำซึ่งให้ผลลัพธ์ที่แปลก หากใครมีวิธีแก้ไขกรุณาช่วยฉันด้วย   -  person Srikanth Reddy    schedule 26.05.2016


คำตอบ (1)


นี่คือตัวอย่างวิธีที่คุณสามารถรวมการเรียกเทมเพลตทั้งสองเข้าด้วยกัน เพื่อให้เอาต์พุตจาก jsonescape ถูกใช้เป็นพารามิเตอร์อินพุตไปยัง escapequote

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="text" />

  <xsl:template match="input">
    <xsl:call-template name="escapeQuote">
      <xsl:with-param name="pText">
        <xsl:call-template name="jsonescape">
          <xsl:with-param name="str" select="." />
        </xsl:call-template>          
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="escapeQuote">
      <xsl:param name="pText" select="concat(normalize-space(.), '')" />
      <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:template name="jsonescape">
   <xsl:param name="str" select="."/>
    <xsl:choose>
      <xsl:when test="contains($str, '\')">
        <xsl:value-of select="concat(substring-before($str, '\'), '\\' )"/>
        <xsl:call-template name="jsonescape">
          <xsl:with-param name="str" select="substring-after($str, '\')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
          <xsl:value-of select="$str"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

ดังนั้นเมื่อป้อนข้อมูลนี้:

<input>Test "out" and \new</input>

ต่อไปนี้เป็นเอาต์พุต

Test \"out\" and \\new

โปรดทราบว่าลำดับเป็นสิ่งสำคัญ เนื่องจากหากคุณกลับลำดับของการเรียกเทมเพลต " จะถูกแปลงเป็น \" ด้วยเทมเพลต escapequote ซึ่งจากนั้นจะถูกแปลงเป็น \\" ด้วยเทมเพลต jsonescape

อีกทางหนึ่ง เนื่องจากเทมเพลตทั้งสองทำสิ่งเดียวกัน โดยใส่ \ หน้าอักขระเฉพาะ คุณจึงสามารถรวมเทมเพลตทั้งสองเป็นเทมเพลตเดียวได้

ลองใช้ XSLT นี้ด้วย

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="text" />

  <xsl:template match="input">
    <xsl:call-template name="jsonescape">
      <xsl:with-param name="str" select="." />
    </xsl:call-template>          
  </xsl:template>

  <xsl:template name="jsonescape">
   <xsl:param name="str" select="."/>
   <xsl:param name="escapeChars" select="'\&quot;'" />
   <xsl:variable name="first" select="substring(translate($str, translate($str, $escapeChars, ''), ''), 1, 1)" />
   <xsl:choose>
      <xsl:when test="$first">
        <xsl:value-of select="concat(substring-before($str, $first), '\', $first)"/>
        <xsl:call-template name="jsonescape">
          <xsl:with-param name="str" select="substring-after($str, $first)"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
          <xsl:value-of select="$str"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
person Tim C    schedule 26.05.2016
comment
ขอบคุณมากฉันขอขอบคุณที่ แค่คำถาม เนื่องจากข้อมูลอาจมีเครื่องหมายคำพูดคู่แรกหรือแบ็กสแลช ในกรณีนี้ รหัสนี้จะใช้งานได้หรือไม่ - person Srikanth Reddy; 26.05.2016
comment
ใช่ ฉันเชื่อว่ามันจะได้ผลอย่างใดอย่างหนึ่งถึงก่อน คุณควรลองและค้นหา :) - person Tim C; 26.05.2016
comment
การเข้ารหัส XSLT แรกทำงานได้อย่างสมบูรณ์แบบในทุกสถานการณ์ ขอขอบคุณ: Tim C - person Srikanth Reddy; 26.05.2016
comment
สุดยอด! โซลูชันทั้งสองใช้งานได้อย่างมีเสน่ห์ ขอบคุณ! - person Hrvoje Golcic; 30.05.2016