我尝试解析元素内容并将其拆分为分隔符,同时将所有元素保留在父级中。我不需要 - 不想要 - 在子元素中找到分隔符。
<data>
<parse-field>Some text <an-element /> more text; cheap win? ;
<another-element>with delimiter;!</another-element>; final text</parse-field>
</data>
应该成为
<data>
<parsed-field>
<field>Some text <an-element /> more text</field>
<field>cheap win?</field>
<field><another-element>with limiter;!</another-element></field>
<field>final text</field>
</parsed-field>
</data>
我有一个黑客攻击的解决方案,可以检查所有&#34;解析字段/文本()&#34;然后用<token />
替换分隔符,然后用第二遍来挑选<token>
周围的部分,但它已被黑了。而且不愉快。我想知道是否有更好的方式。
我正在使用XSLT-2.0,对XSLT-1.0解决方案开放。 SAXON处理器。
答案 0 :(得分:2)
这不是(还是?)一个完整的答案,只是一个可能的方法的概述。如果你想第一次通过这样的话:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="parse-field/text()">
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="';'"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter)">
<field>
<xsl:value-of select="substring-before($text, $delimiter)"/>
</field>
<!-- recursive call -->
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="position()=last()">
<field><xsl:value-of select="$text"/></field>
</xsl:when>
<xsl:when test="$text">
<text><xsl:value-of select="$text"/></text>
</xsl:when>
</xsl:choose>
</xsl:template>
你会得到:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<parse-field>
<text>Some text </text>
<an-element/>
<field> more text</field>
<field> cheap win? </field>
<another-element>with delimiter;!</another-element>
<field/>
<field> final text</field>
</parse-field>
</data>
现在这是一个分组问题,需要对<parse-field>
的元素进行分组,每个组都以<field>
结尾。
答案 1 :(得分:1)
我迄今为止采用的最佳方式,简单形式:
<xsl:variable name="delimiter" select="';'" />
<xsl:template match="foo">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:call-template name="tokenize" />
</xsl:copy>
</xsl:template>
<xsl:template name="tokenize">
<xsl:variable name="rough">
<xsl:apply-templates mode="tokenize" />
</xsl:variable>
<xsl:copy>
<xsl:group-by select="$rough/*" group-ending-with="delimiter">
<field><xsl:apply-templates select="current-group()[not(self::delimiter)]" /></field>
</xsl:group>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="tokenize">
<xsl:copy>
<xsl:apply-templates select="@*|*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="text()" mode="tokenize">
<xsl:analyze-string select="." regex="([^{$delimiter}]*){$delimiter}">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)" /><delimiter/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>