2

我有一个文本,其中有节数。

现在,我想用经文编号将文本分开,并将单个经文的编号作为 ID。

由于我不知道如何从源中获取号码,我只是给了他们连续的号码,但如果可能的话,我希望他们从源头分配他们的实际号码。因此,如果缺少一节,XSLT 不会连续计数,而是跳过一个数字。

但除此之外,我还有一个问题,就是一<l n="1"/>开始我得到了一个空元素。

我认为我的 XSLT<p>也以某种方式匹配,因此实际的 n="1" 变为 n="2"。

我该如何解决?

我的来源:

<root>
<p>1 This is 2 a <hi rend="bold">beautiful</hi> example 3 poem 4 for showing! 5 my problem</p> 
</root>

转换为:

<xsl:stylesheet version="2.0" exclude-result-prefixes="xs"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

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

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

    <xsl:template match="root/p">
        <p>
        <xsl:variable name="words" select="tokenize(text(),'(1|2|3|4|5|6|7|8|9|0)')" as="xs:string*"/>
        <xsl:for-each select="1 to xs:integer(floor(count($words) div 1))">
            <xsl:variable name="vIndex" select="(.)" as="xs:integer"/>
            <l><xsl:attribute name="n"
            select="position()"/>
                <xsl:value-of select="$words[$vIndex]"/>
            </l>
        </xsl:for-each>
        </p>
    </xsl:template>
</xsl:stylesheet>

我得到的是:

<root>
    <p>
      <l n="1"/>
      <l n="2"> This is </l>
      <l n="3"> a beautiful example </l>
      <l n="4"> poem </l>
      <l n="5"> for showing </l>
      <l n="6"> my problem</l>
   </p>
</root>

想要的输出是:

<root>
    <p>
      <l n="1"> This is </l>
      <l n="2"> a <hi rend="bold">beautiful</hi> example </l>
      <l n="3"> poem </l>
      <l n="4"> for showing! </l>
      <l n="5"> my problem</l>
   </p>
</root>

编辑:我在示例中添加了一个元素。

4

2 回答 2

0

返回的第一个元素tokenize将出现在第一个数字之前(在您的情况下为空字符串)。因此,假设您只想要出现在第一个数字之后的内容,则必须从结果中删除第一个元素tokenize(例如,使用该remove函数)。

尝试这个:

<xsl:stylesheet version="2.0" exclude-result-prefixes="xs"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

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

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

    <xsl:template match="root/p">
        <p>
        <xsl:variable name="tokens" select="tokenize(text(),'(1|2|3|4|5|6|7|8|9|0)')" as="xs:string*"/>
        <xsl:variable name="words" select="remove($tokens, 1)" as="xs:string*"/>
        <xsl:for-each select="1 to xs:integer(floor(count($words) div 1))">
            <xsl:variable name="vIndex" select="(.)" as="xs:integer"/>
            <l><xsl:attribute name="n"
            select="position()"/>
                <xsl:value-of select="$words[$vIndex]"/>
            </l>
        </xsl:for-each>
        </p>
    </xsl:template>
</xsl:stylesheet>
于 2013-07-30T13:27:04.783 回答
0

使用analyze-string代替tokenize

<xsl:stylesheet version="2.0" exclude-result-prefixes="xs"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

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

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

    <xsl:template match="root/p">
        <p>
          <xsl:analyze-string select="." regex="([0-9]+)([^0-9]*)">
            <xsl:matching-substring>
              <l name="{regex-group(1)}">
                <xsl:value-of select="regex-group(2)"/>
              </l>
            </xsl:matching-substring>
        </xsl:analyze-string>
     </p>

    </xsl:template>
</xsl:stylesheet>

如果您希望p元素具有元素子元素,则需要一种更复杂的方法:

<xsl:stylesheet version="2.0" exclude-result-prefixes="xs"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

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

    <xsl:template match="node() | @*" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@* |node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="root/p">
        <p>
          <xsl:variable name="children">
            <xsl:apply-templates select="node()" mode="wrap-number"/>
          </xsl:variable>
          <xsl:for-each-group select="$children/node()" group-starting-with="n">
            <l n="{.}">
              <xsl:apply-templates select="current-group() except ."/>
            </l>
          </xsl:for-each-group>
        </p>
    </xsl:template>

    <xsl:template match="p//text()" mode="wrap-number">
      <xsl:analyze-string select="." regex="[0-9]+">
        <xsl:matching-substring>
          <n><xsl:value-of select="."/></n>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
          <xsl:value-of select="."/>
        </xsl:non-matching-substring>
      </xsl:analyze-string>
    </xsl:template>

</xsl:stylesheet>

然而,这仅在确保行的数字包含在元素的文本节点子p元素中时才有效,如果它们也被允许在元素子元素中(例如<p><span>1 This </span>2 is an example.</p>),则需要更多的工作。

于 2013-07-30T13:42:05.660 回答