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