呼叫命名模板下一个兄弟
我有下面的XML:呼叫命名模板下一个兄弟
<Text>
<p id="258">Step.</p>
<p id="1123">Step info.</p>
<p id="258">Step.</p>
<p id="1123">Step info.</p>
<p id="258">Step.</p>
<p id="1123">Step info:</p>
<p id="1123">- Comment.</p>
<p id="1123">- Comment.</p>
<p id="1123">- Comment.</p>
</Text>
我必须把它变成一个DocBook <orderedlist>
:
<orderedlist>
<listitem>
<para>Step.</para>
<para>
<emphasis>Step info.</emphasis>
</para>
</listitem>
<listitem>
<para>Step.</para>
<para>
<emphasis>Step info.</emphasis>
</para>
</listitem>
<listitem>
<para>Step.</para>
<para>
<emphasis>Step info:</emphasis>
</para>
<para>
<emphasis>- Comment:</emphasis>
</para>
<para>
<emphasis>- Comment:</emphasis>
</para>
<para>
<emphasis>- Comment:</emphasis>
</para>
</listitem>
</orderedlist>
我第一次把所有<p id="258">
元素融入<listitem><para>
:
<xsl:template match="AIT:p[@id='258'][1]">
<orderedlist>
<xsl:for-each select="../AIT:p[@id='258']">
<xsl:call-template name="stepNoLine"/>
</xsl:for-each>
</orderedlist>
</xsl:template>
<xsl:template name="stepNoLine">
<listitem>
<para>
<xsl:apply-templates select="*|node()"/>
</para>
</listitem>
</xsl:template>
而我删除所有非第一个元素:
<xsl:template match="AIT:p[@id='258'][position() > 1]"/>
到目前为止好:
<orderedlist>
<listitem>
<para>Step.</para>
</listitem>
<listitem>
<para>Step.</para>
</listitem>
<listitem>
<para>Step.</para>
</listitem>
</orderedlist>
但现在我不知道如何利用<p id="1123">
元素的照顾。两个<p id="258">
之间的所有<p id="1123">
必须是第一个<p id="258">
的兄弟姐妹,以及<listitem>
的子女。还是那句话:
<listitem>
<para>Step.</para>
<para>
<emphasis>Step info.</emphasis>
</para>
</listitem>
我微不足道的尝试失败可耻羞辱:
<xsl:template name="stepNoLine">
<listitem>
<para>
<xsl:apply-templates select="*|node()"/>
</para>
<xsl:if test="following-sibling::AIT:p/@id='1123'">
<xsl:call-template name="stepInfo"/>
</xsl:if>
</listitem>
</xsl:template>
<xsl:template name="stepInfo">
<para>
<emphasis>
<xsl:apply-templates select="*|node()"/>
</emphasis>
</para>
</xsl:template>
我得到的是这样的:
<orderedlist>
<listitem>
<para>Step.</para>
<para>
<emphasis>Step.</emphasis>
</para>
</listitem>
<listitem>
<para>Step.</para>
<para>
<emphasis>Step.</emphasis>
</para>
</listitem>
<listitem>
<para>Step.</para>
<para>
<emphasis>Step.</emphasis>
</para>
</listitem>
</orderedlist>
换句话说,每个<p id="258">
元素被复制两次。我以为<xsl:if>
是当前节点的下一个兄弟,但我显然是错了。
其他尝试(如使用xsl:for-each
而不是xsl:if
)以同样悲惨的方式失败。
有人可以请指出我在正确的方向吗?
XSLT 2.0或3.0,您可以使用for-each-group group-starting-with
:
<xsl:template match="Text">
<orderedlist>
<xsl:for-each-group select="*" group-starting-with="p[@id = 258]">
<listitem>
<xsl:apply-templates select="current-group()"/>
</listitem>
</xsl:for-each-group>
</orderedlist>
</xsl:template>
<xsl:template match="Text/p[@id = 258]">
<para>
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="Text/*[not(self::p[@id = 258])]">
<para>
<emphasis>
<xsl:apply-templates/>
</emphasis>
</para>
</xsl:template>
谢谢你,模板工作打算(虽然我不知道我知道他们是如何做到这一点)。 –
如今的正确答案这种几乎所有的问题将是“使用XSLT 2.0”,但在环境中唯一的XSLT 1.0可用在1.0中解决问题也很有用。
考虑下面的输入,同构的例子所示,但具有不同的字符数据,使其更容易地看到发生了什么:
<Text>
<p id="258">First step.</p>
<p id="1123">Step info for step 1.</p>
<p id="258">Step two.</p>
<p id="1123">Step info for second step.</p>
<p id="258">Step three.</p>
<p id="1123">Step info for third step:</p>
<p id="1123">- Comment on step 3.</p>
<p id="1123">- Comment 2 on step 3.</p>
<p id="1123">- Comment 3 on step 3.</p>
</Text>
有了该输入,这是一个比较容易看到,(一)你的草稿样式表(假设我已经从你的描述中正确地重构了它)确实为每个步骤设置了一个listItem
(尽管它使用了稍微圆满的方法),但是(b)它没有模板匹配Text
元素或任何p
元素与id="1123"
,这意味着默认模板会激发并且我们得到它们的转储在第一个258段的模板输出之后的1123段的字符数据。
<orderedlist>
<listitem>
<para>First step.</para>
<para><emphasis>First step.</emphasis></para>
</listitem>
<listitem>
<para>Step two.</para>
<para><emphasis>Step two.</emphasis></para>
</listitem>
<listitem>
<para>Step three.</para>
<para><emphasis>Step three.</emphasis></para>
</listitem>
</orderedlist>
Step info for step 1.
Step info for second step.
Step info for third step:
- Comment on step 3.
- Comment 2 on step 3.
- Comment 3 on step 3.
代码眼前的问题是,stepNoLine
电话stepinfo
没有做任何事情来改变上下文节点,所以模板应用有处理258款,而不是下面的段落1123的子女。
你正在处理的输入具有的嵌入式元素序列中的大量信息;你的拉式样式表忽略了这些信息,并试图从零开始重新创建它。您的样式表会更简单,如果你让他们通过输入为指导,在什么通常是在XSLT编程为“推”风格着称会做的更好的工作。只为这应该产生listItem
元素,即p
元素与id="258"
儿童应用模板:
在下面的XSLT样式表,为Text
模板调用XSL。 1123段不被该指令处理。
258段元素的模板反过来创建列表项的所有内容:首先是258段,然后是所有后续p
元素的序列id="1123"
。 (我们只对第一个模板应用模板,但第一个模板只处理整个序列。)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="Text">
<xsl:element name="orderedList">
<xsl:apply-templates select="p[@id='258']"/>
</xsl:element>
</xsl:template>
<xsl:template match="p[@id='258']">
<xsl:element name="listitem">
<xsl:element name="para">
<xsl:apply-templates/>
</xsl:element>
<xsl:apply-templates select="following-sibling::*[1]/self::p[@id='1123']"/>
</xsl:element>
</xsl:template>
<xsl:template match="p[@id='1123']">
<xsl:element name="para">
<xsl:apply-templates/>
</xsl:element>
<xsl:apply-templates select="following-sibling::*[1]/self::p[@id='1123']"/>
</xsl:template>
</xsl:stylesheet>
N.B.在模板258个elemetns我们不要试图模板应用到所有适当的兄弟元素与id="1123"
。我们可以,而且一切都将是简单的,如果我们有一个便捷的方式说,XPath 1.0中,“所有紧随p
元素与id="1123"
直到但不包括第一个p
与id="258"
,或父元素结束” ,并且确定地知道我们说得对。说“接下一个兄弟姐妹,当且仅当它是一个p
与id="1123"
,并且比那个元素的模板做同样的事情更容易。当我们到达与id="1123"
其紧随其后的兄弟不是 。id="1123"
,或者有没有以下的兄弟姐妹,递归停止
从修改的输入,这将产生作为输出:
<?xml version="1.0" encoding="UTF-8"?>
<orderedList>
<listitem>
<para>First step.</para>
<para>Step info for step 1.</para>
</listitem>
<listitem>
<para>Step two.</para>
<para>Step info for second step.</para>
</listitem>
<listitem>
<para>Step three.</para>
<para>Step info for third step:</para>
<para>- Comment on step 3.</para>
<para>- Comment 2 on step 3.</para>
<para>- Comment 3 on step 3.</para>
</listitem>
</orderedList>
我相信这是需要什么样的(如果你想换行1123。段落'内容emph
,应该很容易看到在哪里做t帽子。)
@ CMS-McQ,我可以说什么,我向你的掌握鞠躬。非常感谢你。 –
<xsl:template match="Text">
<xsl:element name="orderedlist">
<xsl:apply-templates select="p[@id='258']"/>
</xsl:element>
</xsl:template>
<xsl:template match="p">
<xsl:choose>
<xsl:when test="@id='258'">
<xsl:element name="listitem">
<xsl:element name="para"><xsl:apply-templates /></xsl:element>
<xsl:apply-templates select="following-sibling::p[1][@id = '1123']"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="para">
<xsl:element name="emphasis">
<xsl:apply-templates />
</xsl:element>
</xsl:element>
<xsl:apply-templates select="following-sibling::p[1][@id = '1123']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
全部,谢谢你的回复。但是,我意识到我的问题并不十分精确。 从我的例子中所有的元素都意味着是同
您可以使用XSLT,2.0? –
我使用的是msxsl,但根据Microsoft仅XSLT 1.0。 我看到Saxon-HE 9.8实现了XSLt 3.0 - 会这样吗? –