2

我看到了与 Ruby 等相关的问题。我没有看到任何可以涵盖这种情况的答案。

我正在使用 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" 的内容属性中可以有括号和方括号

谢谢,保罗

4

1 回答 1

0

在您的示例中,没有一个括号匹配,并且都是开括号;在这种情况下,删除不匹配的括号和括号的任务相当于删除所有括号和括号。使用以下功能最容易做到这一点translate

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

如果您确实需要保留匹配的大括号并将表单的输入a(b[c]d(e转换为ab[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>
于 2012-08-19T21:44:30.033 回答