如果某个节点有特定的子节点,则将它分割 [英] Split a node if it has certain children

查看:79
本文介绍了如果某个节点有特定的子节点,则将它分割的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UPDATE:我认为我现在已经回答了大部分问题,除了处理< pgBreak> 之外。您可以在编辑


$下看到我的更新和当前 XSLT b $ b

昨天我问了一个类似的问题,并收到了很好的答案。然而,我后来意识到这并不包括我所有的基础,因此我今天要问一个更详细的问题。

XML IN



 <?xml version =1.0编码= UTF-8 >?; 
< root>
< pgBreak pgId =i/>
< p xml:id =a-01>
< highlight rend =italic> Bacon ipsum dolor sit amet< / highlight>培根夹头五香熏牛肉猪肉臀部,肩膀牛肋骨doner三尖
舌头。三尖地面圆排骨capicola肉饼小腿鼓槌短腰肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< note.ref id =0001>< super> 1< / super>< /note.ref>
< note id =0001>
< p>
您可能需要咨询< highlight rend =italic>拉丁< / highlight>屠夫。祝你好运。
< / p>
< / note>
猪里脊< pgBreak pgId =01/> ribeye培根五香熏腿牛腩,肩猪肩。萨拉米牛腩臀部火腿,尾巴
汉堡牛排牛排猪腿肉短腿排骨生涩小腿牛肉排骨。卡普科拉短肋猪
牛肉丸子j猪肚。 Doner leberkas排骨,侧翼chuck pancetta bresaola培根火腿
猪肉汉堡包fatback。
< / p>
< p xml:id =a-02>
培根ipsum dolor坐amet培根夹头五香熏猪肉臀部,肩膀牛肋骨doner三尖
舌头。三尖地面圆排骨capicola肉饼小腿鼓槌短腰肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< p xml:id =a-03>
培根ipsum dolor坐amet培根夹头五香熏猪肉臀部,肩膀牛肋骨doner三尖
舌头。
< quote>
< p> 1.
三尖地面圆排骨capicola肉饼小腿鼓槌短腰肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< p> 2.
三尖地面圆排骨capicola肉饼小腿鼓槌短腰里面五香粉t-
骨。 Sirloin< pgBreak pgId =02/> turducken排骨短骨t-andouille长条牛排猪里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< p> 3.
三尖地面圆排骨capicola肉饼小腿鼓槌短腰里脊肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< / quote>
< / p>
< / root>



HTML OUT



 <!DOCTYPE HTML> 
< html>
< head>
< meta http-equiv =Content-Typecontent =text / html; charset = UTF-8/>
< title>测试< /标题>
< / head>
< body>
< div id =pg-i>
Page i
< / div>
< p data-chunkid =a-01>
< span class =highlight-italic>培根ipsum dolor sit amet< / span>培根夹头五香熏猪肉臀部,肩膀牛肉肋骨doner三尖
舌头。三尖地面圆排骨capicola肉饼小腿鼓槌短腰
五香粉t-
骨。沙朗turducken排骨t骨和andouille带牛排猪肉里脊咸牛肉
汉堡
培根菲力牛排猪排尾巴。
< span class =noteRefid =0001>< sup> 1< / sup>< / span>< / p>
< div id =note-0001data-chunkid =a-01>
< p>
您可能需要查阅< span class =highlight-italic>拉丁< / span>屠夫。祝你好运。

< / p>
< / div>
< p data-chunkid =a-01>
猪肉腰


< div id =pg-01>
Page 01
< / div>
< p data-chunkId =a-01>
ribeye培根五香熏牛腿沙腿牛排,肩膀猪颈肉。意大利腊肠brisket
臀部火腿,尾巴
汉堡包牛排猪腿肉短腿排骨生涩小腿牛肉排骨。 Capicola
排骨猪
牛肉丸子猪肚。 Doner leberkas排骨,侧翼chuck pancetta bresaola
培根火腿
猪肉汉堡包fatback。
< / p>
< p data-chunkid =a-02>< span class =highlight-italic>培根ipsum dolor sit< / span> amet培根夹头五香熏牛肉猪肉臀部,肩膀牛肋骨doner三尖
舌头。三尖地面圆排骨capicola肉饼小腿鼓槌短腰
五香粉t-
骨。 Sirloin turducken短排骨< span class =highlight-bold> t-bone< / span> andouille strip牛排猪腰肉脯牛肉汉堡包
培根菲力牛排猪排尾巴。

< / p>

< p data-chunkid =a-03>
培根ipsum dolor坐amet培根夹头五香熏牛肉猪肉臀部,肩膀牛肋骨
doner三尖
舌头。

< / p>
< blockquote data-chunkid =a-03>
< p> 1.
三尖地面圆排骨capicola肉饼小腿鼓槌短腰肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< p> 2。
三角地面轮< span class =highlight-italic>短肋< / span> capicola肉饼小腿鼓槌短腰里面五香粉t-
骨头。沙朗
< / p>
< / blockquote>
< div id =pg-02>
Page:02
< / div>
< blockquote data-chunkid =a-03>
< / p>
turducken排骨短骨t-andouille长条牛排猪排里脊咸牛肉
汉堡包培根菲力牛排猪排尾巴。

< / p>
< p> 3.
三尖地面圆排骨capicola肉饼小腿鼓槌短腰里脊肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>

< / blockquote>
< p data-chunkid =a-03>
培根ipsum dolor坐amet培根夹头五香熏牛肉猪肉臀部,肩膀牛肋骨
doner三尖
舌头。

< / p>
< / body>
< / html>

我想将xml转换为html5,但将每个块(xml:id)保留在一起。我想避免使用div(过度使用div),所以将每个p都封装在div中,但我也试图避免无效的HTML。例如,很容易将父级p(xml:id = a-01)包装起来,然后将其包装在其后代中,然而,块级别< div> 和另一个< p> 将是无效的,并且浏览器将在文本结束后将所有内容解释为孤立文本。

我尝试过从 XSLT 问题/ 13823688 /将元素拆分为两个或更多个元素 - 取决于它的子元素>来自昨天的问题。但是,我发现自己处于一个陌生的领域。我也会对解决方案有一个简明扼要的解释,这样我就可以开始更好地理解XSLT,因为看起来在接下来的几个月里,我将花更多时间在它上面。我应该拿起Michael Kay的书或其他东西。

编辑:我正在使用的XSLT的当前版本 >注意:我还没有尝试过分页。此外,我无法获得< meta> 标签以关闭......氧气14不停地抱怨。

b $ b

 < xsl:template match =/> 
< html>
< body>
< xsl:apply-templates />
< / body>
< / html>
< / xsl:template>

< p data-chunkID ={@ xml:id}>
< xsl:apply-templates />
< / p>
< / xsl:template>

< xsl:for-each-group select =node()group-adjacent =boolean((self :: text(),self :: note.ref,self :: highlight))> ;
< xsl:when test =current-grouping-key()>
< p data-chunkID ={../@ xml:id}>
< xsl:apply-templates select =current-group()/>
< / p>
< / xsl:when>
< xsl:when test =self :: p>
< p>
< xsl:apply-templates />
< / p>
< / xsl:when>
< xsl:otherwise>
< xsl:apply-templates select =current-group()/>
< / xsl:otherwise>
< / xsl:for-each-group>
< / xsl:template>

< xsl:template match =note.ref>
< span class =noteRefid ={@ id}>
< xsl:apply-templates />
< / span>
< / xsl:template>

< xsl:template match =super>
< sup>
< xsl:apply-templates />
< / sup>
< / xsl:template>

< xsl:template match =note>
< div id =note - {@ id}data-chunkID ={../@xml:id}>
< p>
< xsl:apply-templates />
< / p>
< / div>
< / xsl:template>


< xsl:template match =quote>
< blockquote data-chunkID ={../@xml:id}>
< p>
< xsl:apply-templates />
< / p>
< / blockquote>
< / xsl:template>



< xsl:template match =highlight>
< span class ={$ class}>
< xsl:apply-templates />
< / span>
< / xsl:when>
< xsl:when test =@ rend [。='bold']>
< span class ={$ class}>
< xsl:apply-templates />
< / span>
< / xsl:when>
< xsl:otherwise>
< span class ={$ class}>
< xsl:apply-templates />
< / span>
< / xsl:otherwise>
< / xsl:template>


解决方案

看起来你的输入与你的输出有一点不一致。 (这是预期的产出,还是你现在得到的产出)?块a-02和a-03在输入中没有< highlight> 元素,但输出具有< span class =highlight。 ..> 元素。另外,块a-03的文本在块引用之后重复。



我相信我已经制作了一个可以在您的示例中执行所有操作的工作解决方案。您可以试试看吗?

 < xsl:stylesheet version =1.0xmlns:xsl =http:// www.w3.org/1999/XSL/Transform\"> 
< xsl:output method =xmlindent =yes/>

< xsl:template match =/>
< html>
< head>
< meta http-equiv =Content-Typecontent =text / html; charset = utf-8/>
< title>测试< /标题>
< / head>
< body>
< xsl:apply-templates />
< / body>
< / html>
< / xsl:template>

< xsl:template match =p | div>
select =$ breaks / following-sibling :: node()[1] [count(。| $ breaks)!= count($ breaks) ]/>

< xsl:apply-templates select =$ breaks | $ firstNonBreak | $ nonBreaksAfterBreakmode =sectChild/>
< / xsl:template>

<! - 模板输出特定层级的块ID属性 - >
< xsl:template name =ChunkId>
< xsl:if test =$ id>
< xsl:attribute name =data-chunkid>
< xsl:value-of select =$ id/>
< / xsl:attribute>
< / xsl:if>
< / xsl:template>

<! - 分割类型 - 注释,分页符,引号 - >
< xsl:template match =pgBreakmode =sectChild>
< div id =pg - {@ pgId}>
< xsl:value-of select =concat('Page',@pgId)/>
< / div>
< / xsl:template>

< xsl:template match =quote | notemode =sectChild>
< xsl:apply-templates />
< / xsl:template>

<! - 接收分割类型
之外的每个内容块的第一个节点,并将处理传递到其块中的自身和同胞上 - >
< xsl:template match =text()| highlight | note.ref | supermode =sectChild>

< xsl:variable name =content>
< / xsl:variable>

< xsl:if test =normalize-space($ content)>
< xsl:call-template name =Nest>
< xsl:with-param name =contentselect =$ content/>
< / xsl:call-template>
< / xsl:if>
< / xsl:template>

<! - 递归模板将节点从顶层输出到内容 - >
< xsl:template name =Nest>
< xsl:param name =topLevelselect =true()/>
< xsl:param name =hierarchy/>
< xsl:param name =content/>

< xsl:variable name =topselect =$ hierarchy [1]/>
< xsl:variable name =remainderselect =$ hierarchy [position()> 1]/>

<! - 如果还有报价或笔记,请不要输出标签,直到我们到达那里 - >
<! - 递归输出被捕获到一个变量中,稍后在这个模板中输出 - >
< xsl:variable name =inside>
< xsl:if test =$ hierarchy>
< xsl:call-template name =Nest>
< xsl:with-param name =topLevelselect =$ topLevel and $ skipTags/>
< xsl:with-param name =hierarchyselect =$ remainder/>
< xsl:with-param name =contentselect =$ content/>
< / xsl:call-template>
< / xsl:if>
< / xsl:variable>

< xsl:when test =not($ hierarchy)>
< xsl:copy-of select =$ content/>
< / xsl:when>
< xsl:when test =$ top / self :: quote>
< blockquote>
< xsl:call-template name =ChunkId/>
< xsl:copy-of select =$ inside/>
< / blockquote>
< / xsl:when>
< xsl:when test =$ top / self :: note>
< div id =note - {$ top / @ id}>
< xsl:call-template name =ChunkId/>
< xsl:copy-of select =$ inside/>
< / div>
< / xsl:when>
< xsl:when test =not($ skipTags)>
< xsl:element name ={name($ top)}>
< xsl:if test =$ topLevel>
< xsl:call-template name =ChunkId/>
< / xsl:if>
< xsl:copy-of select =$ inside/>
< / xsl:element>
< / xsl:when>
< xsl:otherwise>
< xsl:copy-of select =$ inside/>
< / xsl:otherwise>
< / xsl:template>

< xsl:template match =node()mode =buildContent>
< xsl:if test =not(self :: note or self :: quote or self :: pgBreak)>
<! - 输出此节点 - >
<! - 将处理传递到下一个同级 - >
< / xsl:if>
< / xsl:template>

<! - 底层内容 - 文字,注释参考,上标,高亮 - >
< xsl:template match =text()mode =contentOutput>
< xsl:copy-of select =。/>
< / xsl:template>

< xsl:template match =note.refmode =contentOutput>
< span class =noteRefid ={@ id}>
< xsl:apply-templates mode =contentOutput/>
< / span>
< / xsl:template>

< xsl:template match =supermode =contentOutput>
< sup>
< xsl:apply-templates mode =contentOutput/>
< / sup>
< / xsl:template>

< xsl:template match =highlightmode =contentOutput>
< span class ={$ class}>
< xsl:apply-templates mode =contentOutput/>
< / span>
< / xsl:template>
< / xsl:stylesheet>

我相信未封闭的元标记是使用 method =html 。您可能需要使用 method =xml来获取关闭的元标记。使用 method =html,上面的转换会从您的示例输入中生成以下输出:

 < HTML> 
< head>
< META http-equiv =Content-Typecontent =text / html; charset = utf-8>
< title>测试< /标题>
< / head>
< body>
< p data-chunkid =a-01>< span class =highlight-italic> Bacon ipsum dolor sit amet< / span>培根夹头五香熏牛肉猪肉臀部,肩膀牛肋骨doner三尖
舌头。三尖地面圆排骨capicola肉饼小腿鼓槌短腰肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< span class =noteRefid =0001>
< sup> 1< / sup>
< / span>< / p>
< div id =note-0001data-chunkid =a-01>
< p>
您可能需要查阅< span class =highlight-italic>拉丁< / span>屠夫。祝你好运。
< / p>
< / div>
< p data-chunkid =a-01>
猪里脊< / p>
< div id =pg-01>第01页< / div>
< p data-chunkid =a-01> ribeye培根五香熏腿牛腩,肩猪肩。萨拉米牛腩臀部火腿,尾巴
汉堡牛排牛排猪腿肉短腿排骨生涩小腿牛肉排骨。卡普科拉短肋猪
牛肉丸子j猪肚。 Doner leberkas排骨,侧翼chuck pancetta bresaola培根火腿
猪肉汉堡包fatback。
< / p>
< p data-chunkid =a-02>
培根ipsum dolor坐amet培根夹头五香熏猪肉臀部,肩膀牛肋骨doner三尖
舌头。三尖地面圆排骨capicola肉饼小腿鼓槌短腰肉熏牛肉t-
骨。沙朗turducken排骨t骨和鱼排牛排猪肉里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< p data-chunkid =a-03>
培根ipsum dolor坐amet培根夹头五香熏猪肉臀部,肩膀牛肋骨doner三尖
舌头。
< / p>
< blockquote data-chunkid =a-03>
< p>
三尖地面圆排骨capicola肉饼小腿鼓槌短腰里面熏牛肉t-
骨头。沙朗< / p>
< / blockquote>
< div id =pg-02>第02页< / div>
< blockquote data-chunkid =a-03>
< p> turducken排骨排骨t-andouille strip牛排猪排里脊咸牛肉汉堡包
培根菲力牛排猪排尾巴。
< / p>
< / blockquote>

< / body>
< / html>

通过将方法更改为xml并手动添加 meta 元素添加到变换中,您可以获得相同的结果,但使用以下< head>

 < head> 
< meta http-equiv =Content-Typecontent =text / html; charset = utf-8/>
< title>测试< /标题>
< / head>


UPDATE: I think I have answered most of this question now, except the handling of <pgBreak>. you can see my updates and current XSLT at the end of this post under the EDIT

I asked a similar question yesterday, and received good answers. However, I have since realized this didn't cover all my bases so I am asking a more detailed question today.

XML IN

<?xml version="1.0" encoding="UTF-8"?>    
<root>
<pgBreak pgId="i"/>
    <p xml:id="a-01">
        <highlight rend="italic">Bacon ipsum dolor sit amet</highlight> bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip 
        tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
        bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
        bacon filet mignon pork chop tail.
        <note.ref id="0001"><super>1</super></note.ref>
        <note id="0001">
            <p>
                You may need to consult a <highlight rend="italic">latin</highlight> butcher. Good Luck.
            </p>
        </note>   
        Pork loin <pgBreak pgId="01"/> ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
        hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine   
        beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham 
        hock pork hamburger fatback.
    </p>
    <p xml:id="a-02">
        Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip 
        tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
        bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
        bacon filet mignon pork chop tail.
    </p>
    <p xml:id="a-03">
        Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip 
        tongue. 
            <quote>
                <p> 1.
                    Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
                    bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
                    bacon filet mignon pork chop tail.
                </p>
                <p> 2.
                    Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
                    bone. Sirloin <pgBreak pgId="02"/>turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
                    bacon filet mignon pork chop tail.
                </p>
                <p> 3.
                    Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
                    bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
                    bacon filet mignon pork chop tail.
                </p>
            </quote>
    </p>
</root>

HTML OUT

  <!DOCTYPE HTML>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
      <title>Test</title>
   </head>
   <body>
      <div id="pg-i">
        Page i
      </div>
      <p data-chunkid="a-01"> 
         <span class="highlight-italic">Bacon ipsum dolor sit amet</span>bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip 
         tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin
         pastrami t-
         bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef
         hamburger 
         bacon filet mignon pork chop tail.
         <span class="noteRef" id="0001"><sup>1</sup></span></p>
      <div id="note-0001" data-chunkid="a-01">
         <p>
            You may need to consult a <span class="highlight-italic">latin</span> butcher. Good Luck.

         </p>
      </div>
      <p data-chunkid="a-01">   
         Pork loin
      </p>
      <div id="pg-01">
          Page 01
       </div>
        <p data-chunkId="a-01">
         ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket
         rump ham, tail
         hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola
         short ribs swine   
         beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola
         bacon ham 
         hock pork hamburger fatback.
       </p>
      <p data-chunkid="a-02"><span class="highlight-italic">Bacon ipsum dolor sit</span> amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip 
         tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin
         pastrami t-
         bone. Sirloin turducken short ribs <span class="highlight-bold">t-bone</span> andouille strip steak pork loin corned beef hamburger 
         bacon filet mignon pork chop tail.

      </p>

      <p data-chunkid="a-03">
         Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs
         doner tri-tip 
         tongue. 

      </p>
      <blockquote data-chunkid="a-03">
        <p> 1.
            Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
            bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
            bacon filet mignon pork chop tail.
        </p>
         <p>2.
               Tri-tip ground round <span class="highlight-italic">short ribs</span> capicola meatloaf shank drumstick short loin pastrami t-
               bone. Sirloin 
          </p>
       </blockquote>
       <div id="pg-02">
         Page: 02
       </div>
       <blockquote data-chunkid="a-03"> 
         </p>
               turducken short ribs t-bone andouille strip steak pork loin corned beef
               hamburger bacon filet mignon pork chop tail.

         </p>
        <p> 3.
            Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
            bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger 
            bacon filet mignon pork chop tail.
        </p>

      </blockquote>
      <p data-chunkid="a-03">
         Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs
         doner tri-tip 
         tongue. 

      </p>
   </body>
</html>

I would like to transform the xml to html5 but keep each chunk (xml:id) together. I want to avoid divits (overuse of divs) so wraping each p in a div is out, but I also am trying to avoid invalid HTML. for example it would be easy to take the parent p (xml:id=a-01) and wrap it aroud its descendants, however, a block level <div> and another <p> would be invalid, and the browser would intrepret everything after the end of the text as orphaned text.

I have tried various modified XSLTs from my question from yesterday. However, I find myself in a bit of unfamiliar territory. I would also benefit a concise explanation of the solution so I can start to better understand XSLT, as it looks like I will be spending more time with it in the upcoming months. I should probably pick up book by Michael Kay or something.

EDIT: current version of the XSLT I am working with

note: I Haven't attempted the page breaks yet. Also, I cannot get the <meta> tag to close....oxygen 14 keeps complaining about that.

<xsl:template match="/">
    <html>
        <body>
            <xsl:apply-templates/>
        </body>
    </html>
</xsl:template>

<xsl:template match="p[not((parent::note,.//p, .//div))]">
    <p data-chunkID="{@xml:id}">
        <xsl:apply-templates/>
    </p>
</xsl:template>

<xsl:template match="p[.//p, .//div]">
    <xsl:for-each-group select="node()" group-adjacent="boolean((self::text(), self::note.ref,self::highlight))">
        <xsl:choose>
            <xsl:when test="current-grouping-key()">
                <p data-chunkID="{../@xml:id}">
                    <xsl:apply-templates select="current-group()"/>
                </p>
            </xsl:when>
            <xsl:when test="self::p">
                <p>
                    <xsl:apply-templates/>
                </p>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="current-group()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each-group>
</xsl:template>

<xsl:template match="note.ref">
    <span class="noteRef" id="{@id}">
        <xsl:apply-templates/>
    </span>
</xsl:template>

<xsl:template match="super">
    <sup>
        <xsl:apply-templates/>
    </sup>
</xsl:template>

<xsl:template match="note">
    <div id="note-{@id}" data-chunkID="{../@xml:id}">
        <p>
        <xsl:apply-templates/>
        </p>
    </div>
</xsl:template>


<xsl:template match="quote">
    <blockquote data-chunkID="{../@xml:id}">
        <p>
        <xsl:apply-templates/>
        </p>
    </blockquote>
</xsl:template>



<xsl:template match="highlight">
    <xsl:variable name="class" select="concat(name(.),'-',string(@rend))"/>
    <xsl:choose>
        <xsl:when test="@rend[.= 'italic']">
            <span class="{$class}">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
        <xsl:when test="@rend[.= 'bold']">
            <span class="{$class}">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
        <xsl:otherwise>
            <span class="{$class}">
                <xsl:apply-templates/>
            </span>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

解决方案

It looks like your input is a little bit inconsistent with your output. (Is that the expected output, or the output you're getting now)? Chunks a-02 and a-03 have no <highlight> elements in the input, yet the output has <span class="highlight..."> elements. Also, chunk a-03 has text duplicated after the blockquote.

I believe I've produced a working solution that does everything in your example. Could you give this a try?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Test</title>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="p | div">
    <xsl:variable name="breaks" select="note | pgBreak | quote" />
    <xsl:variable name="firstNonBreak" select="node()[count(. | $breaks) != count($breaks)][1]" />
    <xsl:variable name="nonBreaksAfterBreak"
                  select="$breaks/following-sibling::node()[1][count(. | $breaks) != count($breaks)]" />

    <xsl:apply-templates select="$breaks | $firstNonBreak | $nonBreaksAfterBreak" mode="sectChild" />
  </xsl:template>

  <!-- Template to output the chunk id attribute of a particular hierarchy -->
  <xsl:template name="ChunkId">
    <xsl:variable name="id" select="ancestor::*[../self::root]/@xml:id" />
    <xsl:if test="$id">
      <xsl:attribute name="data-chunkid">
        <xsl:value-of select="$id"/>
      </xsl:attribute>
    </xsl:if>
  </xsl:template>

  <!-- Splitting types - notes, page breaks, quotes -->
  <xsl:template match="pgBreak" mode="sectChild">
    <div id="pg-{@pgId}">
      <xsl:value-of select="concat('Page ', @pgId)"/>
    </div>
  </xsl:template>

  <xsl:template match="quote | note" mode="sectChild">
    <xsl:apply-templates />
  </xsl:template>

  <!-- Receives the first node of each block of content outside of the splitting types
       and passes processing onto itself and siblings within its block-->
  <xsl:template match="text() | highlight | note.ref | super" mode="sectChild">

    <xsl:variable name="content">
      <xsl:apply-templates select="." mode="buildContent" />
    </xsl:variable>

    <xsl:if test="normalize-space($content)">
      <xsl:call-template name="Nest">
        <xsl:with-param name="hierarchy" select="ancestor::*[not(self::root)]" />
        <xsl:with-param name="content" select="$content" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <!-- Recursive template to output nodes from the top level down to content -->
  <xsl:template name="Nest">
    <xsl:param name="topLevel" select="true()"/>
    <xsl:param name="hierarchy" />
    <xsl:param name="content" />

    <xsl:variable name="top" select="$hierarchy[1]" />
    <xsl:variable name="remainder" select="$hierarchy[position() > 1]" />

    <!-- If there's a quote or note yet to come, don't output tags until we get there -->
    <xsl:variable name="skipTags" select="boolean($remainder[self::quote or self::note])" />
    <!-- Recursive output is captured in a variable, to be output later in this template -->
    <xsl:variable name="inside">
      <xsl:if test="$hierarchy">
        <xsl:call-template name="Nest">
          <xsl:with-param name="topLevel" select="$topLevel and $skipTags" />
          <xsl:with-param name="hierarchy" select="$remainder" />
          <xsl:with-param name="content" select="$content" />
        </xsl:call-template>
      </xsl:if>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="not($hierarchy)">
        <xsl:copy-of select="$content" />
      </xsl:when>
      <xsl:when test="$top/self::quote">
        <blockquote>
          <xsl:call-template name="ChunkId" />
          <xsl:copy-of select="$inside"/>
        </blockquote>
      </xsl:when>
      <xsl:when test="$top/self::note">
        <div id="note-{$top/@id}">
          <xsl:call-template name="ChunkId" />
          <xsl:copy-of select="$inside"/>
        </div>
      </xsl:when>
      <xsl:when test="not($skipTags)">
        <xsl:element name="{name($top)}">
          <xsl:if test="$topLevel">
            <xsl:call-template name="ChunkId" />
          </xsl:if>
          <xsl:copy-of select="$inside"/>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="$inside"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="node()" mode="buildContent">
    <xsl:if test="not(self::note or self::quote or self::pgBreak)">
      <!-- output this node -->
      <xsl:apply-templates select="self::node()[normalize-space(.)]" mode="contentOutput" />
      <!-- pass processing onto next sibling -->
      <xsl:apply-templates select="following-sibling::node()[1]" mode="buildContent" />
    </xsl:if>
  </xsl:template>

  <!-- Bottom level content - text, note refs, superscript, highlight-->
  <xsl:template match="text()" mode="contentOutput">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="note.ref" mode="contentOutput">
    <span class="noteRef" id="{@id}">
      <xsl:apply-templates mode="contentOutput"/>
    </span>
  </xsl:template>

  <xsl:template match="super" mode="contentOutput">
    <sup>
      <xsl:apply-templates mode="contentOutput"/>
    </sup>
  </xsl:template>

  <xsl:template match="highlight" mode="contentOutput">
    <xsl:variable name="class" select="concat(name(.),'-',string(@rend))"/>
    <span class="{$class}">
      <xsl:apply-templates mode="contentOutput"/>
    </span>
  </xsl:template>
</xsl:stylesheet>

I believe the unclosed meta tags is a result of using method="html". You may need to use method="xml" to get closed meta tags. With method="html", the above transform produces the following output from your sample input:

<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Test</title>
  </head>
  <body>
  <p data-chunkid="a-01"><span class="highlight-italic">Bacon ipsum dolor sit amet</span> bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
    tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
    bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
    bacon filet mignon pork chop tail.
    <span class="noteRef" id="0001">
      <sup>1</sup>
    </span></p>
      <div id="note-0001" data-chunkid="a-01">
      <p>
        You may need to consult a <span class="highlight-italic">latin</span> butcher. Good Luck.
      </p>
    </div>
    <p data-chunkid="a-01">
    Pork loin </p>
    <div id="pg-01">Page 01</div>
    <p data-chunkid="a-01"> ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
    hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine
    beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham
    hock pork hamburger fatback.
  </p>
  <p data-chunkid="a-02">
    Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
    tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
    bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
    bacon filet mignon pork chop tail.
  </p>
  <p data-chunkid="a-03">
    Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
    tongue.
    </p>
      <blockquote data-chunkid="a-03">
      <p>
        Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
        bone. Sirloin </p>
    </blockquote>
    <div id="pg-02">Page 02</div>
    <blockquote data-chunkid="a-03">
      <p>turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
        bacon filet mignon pork chop tail.
      </p>
    </blockquote>

</body>
</html>

By changing the method to "xml" and manually adding the meta element to the transform, you can obtain the same result, but with the following <head>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Test</title>
  </head>

这篇关于如果某个节点有特定的子节点,则将它分割的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆