解析xslt中的字符串

时间:2013-11-19 20:50:21

标签: xslt xslt-2.0

我有以下xml

<xml>
<xref>
 is determined &ldquo;in prescribed manner&rdquo;
</xref>
</xml>

我想看看我们是否可以处理xslt 2并返回以下结果

<xml>
<xref>
   is
</xref>
 <xref>
   determined
</xref>
 <xref>
   &ldquo;in prescribed manner&rdquo;
</xref>
</xml>

我尝试了一些选项,比如替换空格和实体,然后使用for-each循环但不能解决它。可能是我们可以使用xslt 2.0的tokenize函数但不知道如何使用它。任何提示都会有所帮助。

1 个答案:

答案 0 :(得分:1)

@ JimGarrison:对不起,我无法抗拒。 :-)这个XSLT绝对不优雅,但它确实(我假设)大部分工作:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

  <xsl:variable name="left_quote" select="'&lt;'"/>
  <xsl:variable name="right_quote" select="'&gt;'"/>

  <xsl:template name="protected_tokenize">
    <xsl:param name="string"/>

    <xsl:variable name="pattern" select="concat('^([^', $left_quote, ']+)(', $left_quote, '[^', $right_quote, ']*', $right_quote,')?(.*)')"/>

    <xsl:analyze-string select="$string" regex="{$pattern}">
      <xsl:matching-substring>

        <!-- Handle the prefix of the string up to the first opening quote by "normal" tokenizing. -->
        <xsl:variable name="prefix" select="concat(' ', normalize-space(regex-group(1)))"/>
        <xsl:for-each select="tokenize(normalize-space($prefix), ' ')">
          <xref>
            <xsl:value-of select="."/>
          </xref>
        </xsl:for-each>

        <!-- Handle the text between the quotes by simply passing it through. -->
        <xsl:variable name="protected_token" select="normalize-space(regex-group(2))"/>
        <xsl:if test="$protected_token != ''">
          <xref>
            <xsl:value-of select="$protected_token"/>
          </xref>
        </xsl:if>

        <!-- Handle the suffix of the string. This part may contained protected tokens again. So we do it recursively. -->
        <xsl:variable name="suffix" select="normalize-space(regex-group(3))"/>
        <xsl:if test="$suffix != ''">
          <xsl:call-template name="protected_tokenize">
            <xsl:with-param name="string" select="$suffix"/>
          </xsl:call-template>
        </xsl:if>

      </xsl:matching-substring>
    </xsl:analyze-string>
  </xsl:template>

  <xsl:template match="*|@*">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="xref">
    <xsl:call-template name="protected_tokenize">
      <xsl:with-param name="string" select="text()"/>
    </xsl:call-template>
  </xsl:template>

</xsl:stylesheet>

注意:

  • 通常假设空格仅用作标记分隔符,无需保留。
  • &ldquo;rdquo;似乎在XML中无效,尽管它们在HTML中有效。在XSLT中,定义了包含引号字符的变量。一旦找到正确的XML表示,就必须对它们进行调整。您还可以消除变量并将字符放入正则表达式模式中。这将大大简化。
  • <xsl:analyze-string>不允许使用可以计算为空字符串的正则表达式。这是一个小问题,因为前缀和/或受保护的令牌和/或后缀可能是空的。我通过人工在模式的开头添加空格来处理这个问题,这允许我使用+(至少一次出现)而不是*(零次或多次出现)来搜索前缀。