节点集的子串

时间:2014-03-12 07:19:31

标签: xml xslt xpath xslt-2.0

我有这种HTML

<span>Hello this is user874774 writing. <strong>Here is some text in another tag that I can't substring.</strong></span>

说我想提取子字符串(给定一些字符作为输入)

<span>Hello this is user874774 writing. <strong>Here</strong></span> 

有关如何使用XSLT2.0实现此目的的任何想法。由于我的嵌套标签,子字符串函数当然不起作用。

2 个答案:

答案 0 :(得分:1)

编辑:回复您的评论:

  

它可能是我的跨度中的另一个标签,在另一个位置有另一个内容。

然后编写单独的模板并使用参数存储应在substring()之后保留的多个字符。

还有另一个参数start,您可以在其中指定子字符串函数的起始点。如果你总是从字符串的开头取一个子字符串,那么开始当然可以设置为&#34; 0&#34;。

<强>样式表

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:param name="start" select="0"/>
    <xsl:param name="len" select="5"/>

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

    <xsl:template match="text()[parent::span]">
        <xsl:copy/>
    </xsl:template>

    <xsl:template match="text()">
        <xsl:value-of select="substring(.,$start,$len)"/>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<?xml version="1.0" encoding="UTF-8"?>
<span>Hello this is user874774 writing. <strong>Here</strong>
</span>

答案 1 :(得分:1)

如果你想从span的开头计算字符,但是维护原始XML的元素结构,那么我认为你必须使用尾递归模板来接近它从一个兄弟节点到下一个节点的“剩余字符数”。在每个点检查您是否还输出了所需的字符数,如果没有,则继续使用更新的计数处理下一个兄弟节点(元素或文本节点):

  <!-- text nodes are output, truncated if necessary -->
  <xsl:template match="text()" mode="substr" priority="10">
    <xsl:param name="chars" as="xs:integer" tunnel="yes" />
    <xsl:value-of select="substring(., 1, $chars)" />
    <xsl:next-match/><!-- call the common node() template -->
  </xsl:template>

  <!-- for element nodes we copy the start tag and then we continue processing
       with the first child node (which may be a text node or element) -->
  <xsl:template match="*" mode="substr" priority="10">
    <xsl:copy>
      <xsl:sequence select="@*" />
      <xsl:apply-templates select="node()[1]" mode="substr"/>
    </xsl:copy>
    <xsl:next-match/><!-- call the common node() template -->
  </xsl:template>

  <!-- Ignore comments and PIs, or you might want to copy them instead -->
  <xsl:template match="comment()|processing-instruction()"
                mode="substr" priority="10">
    <xsl:apply-templates select="following-sibling::node()[1]" mode="substr" />
  </xsl:template>

  <!-- check the continuation criteria and go to next sibling if appropriate -->
  <xsl:template match="node()" mode="substr" priority="5">
    <xsl:param name="chars" as="xs:integer" tunnel="yes"/>
    <xsl:if test="$chars gt string-length(.)">
      <xsl:apply-templates select="following-sibling::node()[1]" mode="substr">
        <xsl:with-param name="chars" select="$chars - string-length(.)"
                        tunnel="yes"/>
      </xsl:apply-templates>
    </xsl:if>
  </xsl:template>

要启动该过程,请将“substr”模式模板应用于span的第一个子节点,并将必要的字符数作为参数传递

  <xsl:template match="span">
    <xsl:copy>
      <!-- <xsl:sequence select="@*" /> if the span might have attributes -->
      <xsl:apply-templates select="node()[1]" mode="substr">
        <xsl:with-param name="chars" select="38" tunnel="yes" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

根据您的示例输入,chars值为38将产生

<span>Hello this is user874774 writing. <strong>Here</strong></span>

因为第一个文本节点中有34个字符(<span><strong>之间),而<strong>中有四个字符长度限制。 chars值为33只会产生

<span>Hello this is user874774 writing.</span>

截断33个字符后的第一个文本节点,根本不包括strong