2012-05-02 172 views
2

我看到了與Ruby等相關的問題。我沒有看到任何涵蓋這種情況的答案。從XML內容中刪除不匹配的括號和不匹配的括號

我正在使用XSLT來轉換XML文檔。 我不得不使用XSLT 1.0,因爲使用XSLT和XPATH的應用程序仍然在1.0版本上。

你會使用正則表達式在XSL中嵌入Javascript函數嗎?

我有XML代碼:

<document> 
<content name="PROD_MAJ_CLS_CD" type="text" vse-streams="2" u="20" action="cluster" weight="1">2</content> 
<content name="PART_DESC_SHORT" type="text" vse-streams="2" u="22" action="cluster" weight="1">SCREW-ROCKER</content> 
</document> 

內容屬性,其中name = 「PART_DESC_SHORT」 可以有括號和括號它

感謝, 保羅

+0

是的,但要確保在默認情況下隱藏到HTML元素,以避免看到原文JavaScript的執行之前。 –

+0

您能舉出具有無與倫比的parens /括號和預期輸出的輸入示例嗎?你需要處理複雜的情況,如'A [B {c] d} E'(哪個右方括號應該被刪除?) –

+0

下面是一些例子:AXLE GP(SID SEAL(TRUMPE AXLE AS。 W/ ARM AS-PUSH( KIT-COIL(MT –

回答

0

在你的榜樣, 的括號相符,均爲開括號;對於這種情況,刪除不匹配的括號和括號的任務相當於刪除全部括號和括號。這是最容易與translate函數來完成:

<xsl:value-of select="translate(.,'([','')"/> 

如果你真的需要保留匹配的括號和翻譯形式的輸入a(b[c]d(eab[c]de,然後做在XSLT最簡單的方式是用遞歸命名模板它有兩個參數:一個輸入字符串和一個記錄到目前爲止處理的材料的堆棧。 (堆棧可以只是一串由您選擇的分隔符分隔的字符串,您希望不會出現在輸入中。由於您將輸入顯示爲來自屬性值,所以&amp;#x9;可能是安全的選擇(它會除非數據生產者使用數字字符參考),但如果您喜歡,您可以使用|||never-use-this-string-in-a-part-description|||代替。)

在最初的調用中,只傳遞輸入字符串,並讓堆棧默認爲空。

與非空輸入每個呼叫,模板需要一個字符關閉輸入流,並不會與它的正確的事情:

  • 的「(」和「[」,推動一個新的字符串在堆棧上匹配堆棧頂部項目的第一個字符,彈出堆棧兩次,連接項目2,項目1(舊的頂部項目)和字符「]」,以及「]」和「)」。 「或」)「,並將連接推入堆棧。
  • 對於不匹配的「]」和「)」,輸入不均衡,你需要做一些事情。 (此處的代碼會丟棄字符。)
  • 對於任何其他字符,請將其附加到堆棧頂部的項目。

因此,在任何給定的時間,堆棧中除底部之外的每個項目都以未匹配的開括號或括號開頭。每當我們得到一個匹配時,帶括號的字符串就會被追加到堆棧中的下一個項目,從而減少堆棧大小。

當輸入字符串耗盡且堆棧中有多個項目時,堆棧頂部項目中的主要大括號需要被剝離,並且頂部項目(減去大括號)被附加到下一個項目。

一旦堆棧下降到一個項目,該項目包含您想要的字符串。

這是在XSLT:

<xsl:template name="paren-match-or-strip"> 
    <xsl:param name="input"/> 
    <xsl:param name="stack"/> 

    <xsl:variable name="char" 
       select="substring($input,1,1)"/> 
    <xsl:variable name="stacktop" 
       select="substring-before($stack,$sep)"/> 
    <xsl:variable name="stackrest" 
       select="substring-after($stack,$sep)"/> 

    <xsl:choose> 
    <xsl:when test="not($input = '')"> 
     <xsl:choose> 
     <xsl:when test="$char = '(' or $char = '['"> 
      <!--* Push another potential-left-brace on the stack *--> 
      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
         select="concat(
           $char, 
           $sep, 
           $stack 
           )"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="($char = ']' and substring($stacktop,1,1) = '[') 
         or 
         ($char = ')' and substring($stacktop,1,1) = '(') 
         "> 
      <!--* Match the left brace at the top of the stack *--> 
      <xsl:variable name="stacktop2" 
         select="substring-before($stackrest,$sep)"/> 
      <xsl:variable name="stackrest2" 
         select="substring-after($stackrest,$sep)"/> 

      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
         select="concat(
           $stacktop2, 
           $stacktop, 
           $char, 
           $sep, 
           $stackrest 
           )"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="$char = ']' or $char = ')'"> 
      <!--* Unmatched right brace, drop it silently *-->  
      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
         select="$stack"/> 
      </xsl:call-template> 
     </xsl:when>  
     <xsl:otherwise> 
      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
          select="concat(
            $stacktop, 
            $char, 
            $sep, 
            $stackrest 
            )"/> 
      </xsl:call-template> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:when test="$input = '' and contains($stackrest,$sep)"> 
     <!--* Input is exhausted and at least one unmatched 
      * parenthesis is on the stack. 
      *--> 
     <xsl:variable name="stacktop2" 
        select="substring-before($stackrest,$sep)"/> 
     <xsl:variable name="stackrest2" 
        select="substring-after($stackrest,$sep)"/> 

     <xsl:call-template name="paren-match-or-strip"> 
     <xsl:with-param name="input" 
         select="$input"/> 
     <xsl:with-param name="stack" 
         select="concat(
           $stacktop2, 
           substring($stacktop,2), 
           $sep, 
           $stackrest2 
           )"/> 
     </xsl:call-template> 

    </xsl:when> 
    <xsl:otherwise> 
     <!--* input is exhausted, stack only has one item *--> 
     <xsl:value-of select="substring-before($stack,$sep)"/> 
    </xsl:otherwise> 
    </xsl:choose> 

</xsl:template>