我试图将一个节点移动到它之前兄弟姐妹的孩子身上,而且事实上一切都处于同一水平,这对我来说有点棘手。
我输入的插图:
<dl>
<dlentry>
<dt> Title 1 </dt>
<dd> Title 1's definition </dd>
<dt> Title 2 </dt>
<dd> Title 2's definition </dd>
<dt> Title 3 </dt>
<dd> Title 3's definition </dd>
</dlentry>
</dl>
<p> part of title 3's definition </p>
<p> another part of title 3's definition </p>
我尝试做的是在底部取出这两个<p>
元素,并将其文本连接到<dd>
中最后一个<dlentry>
元素文本的末尾,因为它们是一部分“Title 3”的定义。
期望的输出:
<dl>
<dlentry>
<dt> Title 1 </dt>
<dd> Title 1's definition </dd>
<dt> Title 2 </dt>
<dd> Title 2's definition </dd>
<dt> Title 3 </dt>
<dd> Title 3's definition part of title 3's definition another part of title 3's definition </dd>
</dlentry>
</dl>
我正在处理的另一个问题是因为XHTML在我的源文档中有多糟糕,我需要对这些<p>
元素的文本进行正则表达式匹配,以确保它没有命中文档中的任何其他位置。
我能够根据需要成功插入第一个<p>
的文本但是无法让它工作,所以我可以进行正则表达式匹配并获得第二个
元素文本也进入所需的位置。
这是我的样式表中的代码片段,使用XSLT 2.0。
<xsl:analyze-string select="."
regex="my regex expression here">
<xsl:template match="dlentry">
<xsl:matching-substring>
<dlentry>
** <xsl:copy-of select="node()[ position() lt last()]"/>
<dd>
<xsl:copy-of select="node()[last()]/text()" />
<xsl:copy-of select=" parent::node()/following-sibling::node()[1]/text()"/>
</dd>
</dlentry>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select=".">
</xsl:non-matching-substring>
</xsl:template>
<xsl:template match="p[preceding-sibling::node()[1][self::node()[name(.)='dl']]]" />
<xsl:template match="p[preceding-sibling::node()[2][self::node()[name(.)='dl']]]" />
在带有星号的代码行中,Saxon抛出一个错误,说“这里不能使用Axis step child :: node():上下文项是一个原子值。”我不熟悉analyze-string但是如果我在analyze-string之外运行我的副本选择并且只是在模板中,它运行正常。
很抱歉,这个问题有点长,但我想分享我现在所拥有的一切。
提前致谢。
答案 0 :(得分:2)
这个简短而简单的XSLT 1.0 (当然它也是XSLT 2.0):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match="p" use="generate-id(preceding-sibling::dl[1])"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dlentry/dd[last()]">
<dd>
<xsl:apply-templates select=
"(.|key('kFollowing', generate-id(ancestor::dl[1])))/text()"/>
</dd>
</xsl:template>
<xsl:template match="p"/>
</xsl:stylesheet>
应用于提供的XML文档:
<html>
<dl>
<dlentry>
<dt> Title 1 </dt>
<dd> Title 1's definition </dd>
<dt> Title 2 </dt>
<dd> Title 2's definition </dd>
<dt> Title 3 </dt>
<dd> Title 3's definition </dd>
</dlentry>
</dl>
<p> part of title 3's definition </p>
<p> another part of title 3's definition </p>
</html>
会产生想要的正确结果:
<html>
<dl>
<dlentry>
<dt> Title 1 </dt>
<dd> Title 1's definition </dd>
<dt> Title 2 </dt>
<dd> Title 2's definition </dd>
<dt> Title 3 </dt>
<dd> Title 3's definition part of title 3's definition another part of title 3's definition </dd>
</dlentry>
</dl>
</html>
答案 1 :(得分:1)
不确定效率,但是在xsl之后应该产生请求的输出:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/doc">
<xsl:for-each select="dl">
<dl>
<xsl:for-each select="dlentry">
<xsl:apply-templates select="dt|dd"/>
</xsl:for-each>
</dl>
</xsl:for-each>
</xsl:template>
<xsl:template match="dt">
<dt><xsl:value-of select="."/></dt>
</xsl:template>
<xsl:template match="dd">
<dd>
<xsl:value-of select="."/>
<!-- Check if this is the last element (= no dd/dd after) -->
<xsl:if test="not(following-sibling::*)">
<!-- Select dl's next sibling, if it's a <p> -->
<xsl:for-each select="../../following-sibling::*[1][name() = 'p']">
<!-- Call recursive template -->
<xsl:call-template name="concat"/>
</xsl:for-each>
</xsl:if>
</dd>
</xsl:template>
<xsl:template name="concat">
<xsl:value-of select="."/>
<!-- Select p's next sibling, if it's a <p> -->
<xsl:for-each select="following-sibling::*[1][name() = 'p']">
<!-- Call recursive template -->
<xsl:call-template name="concat"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这是我测试的输入:
<doc>
<dl>
<dlentry>
<dt> Title 1 </dt>
<dd> Title 1's definition </dd>
<dt> Title 2 </dt>
<dd> Title 2's definition </dd>
<dt> Title 3 </dt>
<dd> Title 3's definition </dd>
</dlentry>
</dl>
<p> part of title 3's definition </p>
<p> another part of title 3's definition </p>
</doc>