Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT将文本除以分隔符,并给它一个元素和属性号_Xml_Xslt - Fatal编程技术网

Xml XSLT将文本除以分隔符,并给它一个元素和属性号

Xml XSLT将文本除以分隔符,并给它一个元素和属性号,xml,xslt,Xml,Xslt,我有一篇有诗句编号的文章 现在,我想通过诗句编号来分隔文本,并将单个诗句的编号作为ID 由于我不知道如何从来源获取数字,我只给了他们连续的数字,但如果可能的话,我更希望他们从来源分配实际数字。因此,如果缺少一节,XSLT不会连续计数,而是跳过一个数字 但除此之外,我还有一个问题,我在开始时得到一个空元素 我认为我的XSLT在某种程度上也与匹配,因此实际的n=“1”变成了n=“2” 我怎样才能解决这个问题 我的消息来源: 1这是一个美丽的例子3诗4展示!5我的问题 转化为: <xsl:s

我有一篇有诗句编号的文章

现在,我想通过诗句编号来分隔文本,并将单个诗句的编号作为ID

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

但除此之外,我还有一个问题,我在开始时得到一个空元素

我认为我的XSLT在某种程度上也与
匹配,因此实际的n=“1”变成了n=“2”

我怎样才能解决这个问题

我的消息来源:


1这是一个美丽的例子3诗4展示!5我的问题

转化为:

<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>


这是
一个很好的例子
诗
谢谢你的展示!
我的问题



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

标记化返回的第一个元素将出现在第一个数字之前(在您的示例中,是一个空字符串)。因此,假设您只想要出现在第一个数字之后的内容,那么您必须从
标记化
的结果中删除第一个元素(例如,使用
删除
函数)

试试这个:

<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>



使用
分析字符串
而不是
标记化

<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
元素的文本节点子元素中时,这才起作用,如果它们也被允许包含在元素子元素中(例如
1这2是一个示例。

),则需要进行更多的工作。

非常感谢,这正是我想要的。我将坚持您的答案,因为tokenize似乎不适用于更长的字符串。但我意识到它不会复制字符串中的元素。我不知道这会成为一个问题,因此我没有在我的示例中包含元素。我尝试了使用copy of select,而不是value of,但我得出的结论是,我必须以某种方式将元素输入正则表达式。例如,字符串中有文本,不会被复制。有什么提示吗?
analyze string
对普通字符串进行操作,而不是对节点树进行操作。如果您有要保留的子元素,则建议使用的简单模板对
p
元素的内容执行
analyze string select=“.”
,但该模板不起作用。您需要分两步使用转换,第一步确保将索引号转换为可以分组的元素(例如,将
1…2…

转换为
1…2…

),第二步根据需要进行包装,方法是执行
..
@smk,我编辑了我的答案,以展示如何处理包含元素子元素的
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() | @*">
        <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>
<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>