键:选择前一兄弟节点的最后一个子节点

时间:2012-06-13 21:27:39

标签: xml xslt xpath

我有一些(格式错误的DITA)XML格式如下:

<dl>
<dlentry><dt>BLARG</dt>
<dd>BLARG Definition</dd>
<dt>BLARG2</dt>
<dd>BLARG2 Definition</dd></dlentry>
</dl>
<dl>
<dlentry><dt>BLARG3</dt>
<dd>BLARG3 Definition</dd></dlentry>
</dl>
<p>Continuation of BLARG3 definition.</p>
<note>Note pertaining to BLARG3 definition</note>

等等。

我要做的是将这一系列<dl>元素合并为一个<dl>,如下所示:

<dl>
    <dlentry><dt>BLARG</dt>
       <dd>BLARG Definition</dd></dlentry>
    <dlentry><dt>BLARG2</dt>
       <dd>BLARG2 Definition</dd></dlentry>
    <dlentry><dt>BLARG3</dt>
       <dd>BLARG3 definition. Continuation of BLARG3 definition.
       <note>Note pertaining to BLARG3 definition</note></dd></dlentry>
<dl>

我正在尝试使用密钥根据前面<p>的{​​{1}}值对任何<note>generate-id()节点编制索引,如下所示:

<dd>

2 个答案:

答案 0 :(得分:1)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <!-- using a test root -->
    <xsl:template match="/test">
        <dl>
            <xsl:apply-templates select="dl/*/dt" />
        </dl>
    </xsl:template>

    <!-- assuming that we have always a dd for each dt -->
    <xsl:template match="dt">
        <dlentry>
            <xsl:copy-of select="."/>
            <dd>
             <xsl:value-of select="following::*[1]"/>
             <!-- just check the node after dd or dlentry or dl -->
             <xsl:apply-templates select="following::*[2]
                [local-name()='p' or 
                 local-name()='note' or 
                 local-name()='table']"/>
            </dd>

        </dlentry>
    </xsl:template>

    <xsl:template match="p|note|table">
        <xsl:copy-of select="."/>
        <!-- copy next node only if wanted -->
        <xsl:apply-templates select="following::*[1]
                [local-name()='p' or 
                 local-name()='note' or 
                 local-name()='table']"/>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

此转化

<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|note"
      use="generate-id(preceding-sibling::dl[1]/dlentry)"/>

     <xsl:template match="node()|@*">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>

     <xsl:template match="dl[1]">
      <dl>
       <xsl:apply-templates select="../dl/dlentry"/>
      </dl>
     </xsl:template>

     <xsl:template match="dd">
      <dd>
        <xsl:value-of select="."/>
        <xsl:copy-of select="key('kFollowing', generate-id(..))/self::p/text()"/>
        <xsl:copy-of select="key('kFollowing', generate-id(..))/self::note"/>
      </dd>
     </xsl:template>
     <xsl:template match="dl|p|note"/>
</xsl:stylesheet>

应用于以下XML文档(提供的片段包装在单个顶部元素中):

<t>
    <dl>
        <dlentry>
            <dt>BLARG</dt>
            <dd>BLARG Definition</dd>
            <dt>BLARG2</dt>
            <dd>BLARG2 Definition</dd>
        </dlentry>
    </dl>
    <dl>
        <dlentry>
            <dt>BLARG3</dt>
            <dd>BLARG3 Definition</dd>
        </dlentry>
    </dl>
    <p>Continuation of BLARG3 definition.</p>
    <note>Note pertaining to BLARG3 definition</note>
</t>

会产生想要的正确结果:

<t>
   <dl>
      <dlentry>
         <dt>BLARG</dt>
         <dd>BLARG Definition</dd>
         <dt>BLARG2</dt>
         <dd>BLARG2 Definition</dd>
      </dlentry>
      <dlentry>
         <dt>BLARG3</dt>
         <dd>BLARG3 DefinitionContinuation of BLARG3 definition.<note>Note pertaining to BLARG3 definition</note>
         </dd>
      </dlentry>
   </dl>
</t>

我故意没有在两个文本节点之间生成". "分隔符,因为这没有被声明为要求,可能只是OP的装饰。这样做需要额外的努力,并留给读者练习:)。