2016-09-26 81 views
0

我正在使用XSLT從標籤中刪除括號,但僅當它們位於開頭和結尾處並僅在鏈接時。當在字符串的開頭和結尾處鏈接時刪除括號xslt

例如

(標籤(1))變成標籤(1)

(標籤)(1)保持(標籤)(1)


編輯特定性

更多示例:

(1)變爲1

(這是)(一(標籤))保持(這是)(一(標籤))

(這(是)(標籤))變爲這(是)(標籤)

之間

我原本以爲通過依次測試字符,並保持一個計數器來跟蹤他們是否有聯繫解決任何變化,但我失去了一些東西仍然。任何援助表示讚賞。

這裏是我當前的代碼:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink" exclude-result-prefixes="xs" version="2.0"> 
<xsl:output indent="yes" method="xml" doctype-system="\\ukfs11\Bks_RAPS\XML\DTDs\TFB\TFB.dtd"/> 
<xsl:param name="labelstack"/> 
<xsl:param name="labeltest"/> 


<xsl:template match="//label[matches(.,'^\(.*\)$')]"> 
    <xsl:param name="labelstack" select="substring(., 1, string-length(.) - 1)"/> 
    <xsl:param name="labelcounter"/> 
    <xsl:call-template name="loop1"> 
     <xsl:with-param name="labelstack" select="$labelstack"/> 
     <xsl:with-param name="labelcounter" select="0"/> 
    </xsl:call-template> 
</xsl:template> 


<xsl:template name="loop1"> 
    <xsl:param name="labeltest" select="substring($labelstack, 1,1)"/> 
    <xsl:param name="labelstack" select="substring($labelstack, 2)"/> 
    <xsl:param name="labelcounter"/> 
    <xsl:choose> 
     <xsl:when test="string-length($labeltest) = 0"> 
     <xsl:copy> 
       <xsl:value-of select="substring(., 2, string-length(.) - 1)"/> 
     </xsl:copy> 
     </xsl:when> 

     <xsl:when test="$labeltest = '('"> 
      <xsl:variable name="labelcounter" select="$labelcounter + 1"/> 
      <xsl:choose> 

       <xsl:when test="$labelcounter != 0"> 
        <xsl:call-template name="loop1"> 
         <xsl:with-param name="labelcounter" select="$labelcounter"/> 
         <xsl:with-param name="labelstack" select="$labelstack"/> 
        </xsl:call-template> 
       </xsl:when> 

       <xsl:otherwise> 
        <xsl:copy> 
         <xsl:apply-templates select="node()|@*"/> 
        </xsl:copy> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 

     <xsl:when test="$labeltest = ')'"> 
      <xsl:variable name="labelcounter" select="$labelcounter - 1"/> 
      <xsl:choose> 

       <xsl:when test="$labelcounter != 0"> 
        <xsl:call-template name="loop1"> 
         <xsl:with-param name="labelcounter" select="$labelcounter"/> 
         <xsl:with-param name="labelstack" select="$labelstack"/> 
        </xsl:call-template> 
       </xsl:when> 

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

      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:call-template name="loop1"> 
         <xsl:with-param name="labelcounter" select="$labelcounter"/> 
         <xsl:with-param name="labelstack" select="$labelstack"/> 
        </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

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

回答

0

樣式表

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:mf="http://example.com/mf" 
    exclude-result-prefixes="xs mf" 
    version="2.0"> 

    <xsl:function name="mf:nested-characters" as="xs:boolean"> 
     <xsl:param name="input" as="xs:string"/> 
     <xsl:param name="pair" as="xs:string*"/> 
     <xsl:sequence select="mf:match-pairs(string-to-codepoints($input), string-to-codepoints($pair[1]), string-to-codepoints($pair[2]), 0)"/> 
    </xsl:function> 

    <xsl:function name="mf:match-pairs" as="xs:boolean"> 
     <xsl:param name="input" as="xs:integer*"/> 
     <xsl:param name="open" as="xs:integer"/> 
     <xsl:param name="close" as="xs:integer"/> 
     <xsl:param name="count" as="xs:integer"/> 
     <xsl:sequence select=" 
      if (not(exists($input))) 
      then $count eq 0 
      else if ($input[1] eq $open) 
       then mf:match-pairs(subsequence($input, 2), $open, $close, $count + 1) 
       else if ($input[1] eq $close) 
         then (if ($count eq 1 and exists($input[2])) 
          then false() 
          else mf:match-pairs(subsequence($input, 2), $open, $close, $count - 1)) 
         else mf:match-pairs(subsequence($input, 2), $open, $close, $count)"/> 
    </xsl:function> 

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

    <xsl:template match="label[matches(., '^\(.*\)$')][mf:nested-characters(., ('(', ')'))]"> 
     <xsl:copy> 
      <xsl:value-of select="replace(., '^\(|\)$', '')"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

轉換

<root> 
    <label>(label (1))</label> 
    <label>(label) (1)</label> 
    <label>(1)</label> 
    <label>(This is)(a (label))</label> 
    <label>(This (is) (a label))</label> 
</root> 

<root> 
    <label>label (1)</label> 
    <label>(label) (1)</label> 
    <label>1</label> 
    <label>(This is)(a (label))</label> 
    <label>This (is) (a label)</label> 
</root> 
+0

我也不是,我有10,000本電子書進行轉換,所以我承擔最複雜的輸入,我希望它能夠處理儘可能多的圓括號,因此我的計數器解決方案在理論上應該可以像我一樣處理它。 這個想法是,每遇到一個「(」它遇到的計數器就會增加1,每遇到一次「)」它就會將它減少1.如果字符串到達​​最後一個字符之前沒有達到0,那麼我刪除括號。通過這種方式,它可以像它想要的那樣深入和複雜,它應該仍然有效。 –

+0

@DavidBrowne,我編輯了代碼示例,並試圖實現檢查到一個函數,該函數處理每個(每個)字符的代碼點。 –

+0

今天早上我已經測試了50個電子書上的代碼,它正在做我所需要的。感謝您的時間。 –