Xml Xpath/XSLT返回部分字符串
我正在使用XSLT2.0和XPath2.0。我在写一个Xml Xpath/XSLT返回部分字符串,xml,xslt,xpath,Xml,Xslt,Xpath,我正在使用XSLT2.0和XPath2.0。我在写一个时遇到了问题,它会去掉段落的前导段落号,同时仍然保留段落中的所有元素。例如: <p>(1) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p> (1)本段可能包含斜体、粗体和其他元素 为此: <p> <b>(1)<b> This
时遇到了问题,它会去掉段落的前导段落号,同时仍然保留段落中的所有元素。例如:
<p>(1) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
(1)本段可能包含斜体、粗体和其他元素
为此:
<p>
<b>(1)<b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.
</p>
(1) 本段可能有斜体、粗体和其他元素。
下面是我的一段详细代码,部分满足了我的需要:
<xsl:template match="p[substring(.,1,1) = '('][string-length(substring-before(.,')')) < 5]">
<xsl:variable name="paragraphnumber">
<xsl:value-of select="substring-after(substring-before(.,')'),'(')"/>
</xsl:variable>
<xsl:variable name="parenthesednumber" select="concat('(',$paragraphnumber,')')"/>
<p>
<b>
<xsl:value-of select="$parenthesednumber"/>
</b>
<xsl:value-of select="translate(.,$parenthesednumber,'')"/>
</p>
</xsl:template>
模板匹配确保我们只匹配以(
)开头的段落,结束语)
之后只有5个字符,允许使用3个字符的段落编号或文本
我遇到的问题是的最后一个
值,我可以得到文本,但不能得到段落中的其他元素。我认为最好是在段落中具有(n)个数字的第一个文本节点上进行匹配,这样您就可以自由地使用标识转换来复制/转换其他节点(文本/元素)在该段中
警告:我手头只有一个XPath/XSLT1.0处理器,但我相信这里没有1.0和2.0之间的区别
样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="p/text()[1][substring(.,1,1) = '('][string-length(substring-before(.,')')) < 5]">
<xsl:variable name="paragraphnumber">
<xsl:value-of select="substring-after(substring-before(.,')'),'(')" />
</xsl:variable>
<xsl:variable name="parenthesednumber" select="concat('(',$paragraphnumber,')')" />
<b>
<xsl:value-of select="$parenthesednumber" />
</b>
<xsl:value-of select="translate(.,$parenthesednumber,'')" />
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出:
<p><b>(1)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
(1)本段可能包含斜体、粗体和其他元素
我认为,在这里使用单独的模板是一种更好的方法。通过这样做,您可以确保“权力划分”,并更容易地找出错误代码
下面的样式表通过matches()
使用XSLT中的正则表达式功能:
输出
<?xml version="1.0" encoding="UTF-8"?><p><b>(1)</b>This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
为什么您的方法无效
我假设这一行:
<xsl:value-of select="translate(.,$parenthesednumber,'')"/>
您打算输出
的剩余内容。但是,您只输出p
元素的文本内容,而不输出其子元素。您还需要明确声明它们也应该被处理-例如,通过使用apply templates
我将使用以下方法:
<p>(2) Text1 <b/>(1) Text2</p>
<xsl:template match="p/text()[1]">
<xsl:analyze-string select="." regex="\(\d+\)">
<xsl:matching-substring>
<b><xsl:value-of select="."/></b>
要将“p”元素转换为在第一个文本节点中包含额外“b”元素的元素。正如Michael Kay所建议的,您可以执行以下操作
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()[1]">
<xsl:analyze-string select="." regex="\(.{{1,3}}\)">
<xsl:matching-substring>
<b><xsl:value-of select="."/></b>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
它搜索第一个文本节点,以“(”开头,以“)”结尾,内有1-3个字符。应用于XML输入时,如:
<root>
<p>(abc4) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p>(123) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p>(1ab) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p>(a1) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
</root>
(abc4)本段可能有斜体、粗体和其他元素
(123)本段可包含斜体、粗体和其他元素
(1ab)本段可包含斜体、粗体和其他元素
(a1)本段可采用斜体、粗体和其他元素
它产生:
<root>
<p>(abc4) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p><b>(123)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p><b>(1ab)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p><b>(a1)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
</root>
(abc4)本段可能有斜体、粗体和其他元素
(123)本段可包含斜体、粗体和其他元素
(1ab)本段可包含斜体、粗体和其他元素
(a1)本段可采用斜体、粗体和其他元素
我想知道作为两个模板,这是否会更好…一个是发现段落并插入p的子::b。然后模板2将现在不需要的(a)从段落文本的开头移除?这不会从任何文本节点的开头移除\([0-9]+\)
,而不仅仅是
之后的第一个文本节点吗?也就是说,如果您的输入是Text1(1)Text2
,它也会删除(1)?您是对的。谢谢你发现这个。我将更新我的样式表。OP希望允许使用3个字符的段落编号或文本。此
不会选择以(abc)
开头的
节点。我选择了Joel的答案,因为我喜欢使用analyze字符串。但是我也喜欢这个答案。我第一次使用。。我喜欢。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()[1]">
<xsl:analyze-string select="." regex="\(.{{1,3}}\)">
<xsl:matching-substring>
<b><xsl:value-of select="."/></b>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
<root>
<p>(abc4) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p>(123) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p>(1ab) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p>(a1) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
</root>
<root>
<p>(abc4) This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p><b>(123)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p><b>(1ab)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
<p><b>(a1)</b> This paragraph may have <i>italics</i>, <b>bold</b> and other elements.</p>
</root>