我有以下xml
<xml>
<xref>
is determined “in prescribed manner”
</xref>
</xml>
我想看看我们是否可以处理xslt 2并返回以下结果
<xml>
<xref>
is
</xref>
<xref>
determined
</xref>
<xref>
“in prescribed manner”
</xref>
</xml>
我尝试了一些选项,比如替换空格和实体,然后使用for-each循环但不能解决它。可能是我们可以使用xslt 2.0的tokenize函数但不知道如何使用它。任何提示都会有所帮助。
答案 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="'<'"/>
<xsl:variable name="right_quote" select="'>'"/>
<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>
注意:
“
和rdquo;
似乎在XML中无效,尽管它们在HTML中有效。在XSLT中,定义了包含引号字符的变量。一旦找到正确的XML表示,就必须对它们进行调整。您还可以消除变量并将字符放入正则表达式模式中。这将大大简化。<xsl:analyze-string>
不允许使用可以计算为空字符串的正则表达式。这是一个小问题,因为前缀和/或受保护的令牌和/或后缀可能是空的。我通过人工在模式的开头添加空格来处理这个问题,这允许我使用+
(至少一次出现)而不是*
(零次或多次出现)来搜索前缀。