1

编辑:对于那些将来会遇到这个问题的人来说,这是一个写得很糟糕的问题。这不是我所追求的。 这个问题也可能对你有用。

所以,我XSLT 这几天一直在努力复习。我对它非常陌生,过去的大部分时间都XQuery用于转换我的 XML。我被困在一个相当简单的问题上,但是环顾四周,我还没有找到明确的解决方案。简单地说,我想根据它的子元素将一些元素分成两部分。

例如,如果我的 XML 如下所示:

<?xml version="1.0" encoding="UTF-8"?>    
<root>
      <p>
         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.
         <note.ref id="0001"><super>1</super></note.ref>
         <note id="0001">
           <p>
             You may need to consult a latin butcher. Good Luck.
           </p>
         </note>   
       Pork loin 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>
    </root>

在我运行我之后,我xsl留下了如下内容:

<html>
<body>
   <p>
         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.
         <span class="noteRef" id="0001"><sup>1</sup></span>
         <div id="note-0001"> 
           <p>
               You may need to consult a latin butcher. Good Luck.
           </p>
         </div>
           Pork loin 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>
</body>
</html>

这样做的问题显然是一个HTML <p>不能有一个<div>作为孩子,让一个孤独的另一个<p>作为孙子。这只是无效的。浏览器(例如 chromium)可能会在点击 时呈现第一段结尾<div>,适当地将注释包装在它自己的<p>中,但在注释之后留下文本 orpahened。这样应用到的任何 CSS<p>都将无法应用。

如何<p>根据元素后代将一个元素分成两个?

期望的输出

  <html>
    <body>
       <p>
             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.
             <span class="noteRef" id="0001"><sup>1</sup></span><
</p>
             <div id="note-0001"> 
               <p>
                   You may need to consult a latin butcher. Good Luck.
               </p>
             </div>
<p>
               Pork loin 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>
    </body>
    </html>

我已经稍微抽象了我的问题,所以XSL我尝试过的以下内容可能会略有偏差。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    exclude-result-prefixes="xs xd" version="2.0">


<xsl:template match="/">

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

    <xsl:template match="p">
        <p>
            <xsl:apply-templates/>
        </p>
    </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}">
            <xsl:apply-templates/>
        </div>
    </xsl:template>

</xsl:stylesheet>
4

2 回答 2

1

这可能太简化了,但是您可以尝试匹配包含 a 的 atext()并将其包装(以及任何跟随的)...pnotenote.reftext()

XML 输入

<root>
    <p>
        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.
        <note.ref id="0001"><super>1</super></note.ref>
        <note id="0001">
            <p>
                You may need to consult a latin butcher. Good Luck.
            </p>
        </note>   
        Pork loin 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>
</root>

XSLT 2.0(也可以作为 1.0 工作)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

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

    <xsl:template match="p[note]">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="p[note]/text()">
        <p>
            <xsl:value-of select="normalize-space(.)"/>
            <xsl:apply-templates select="following-sibling::note.ref" mode="keep"/>
        </p>
    </xsl:template> 

    <xsl:template match="note">
        <div id="note-{@id}">
            <xsl:apply-templates/>
        </div>
    </xsl:template>

    <xsl:template match="note.ref"/>
    <xsl:template match="note.ref" mode="keep">
        <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="text()">
        <xsl:value-of select="normalize-space(.)"/>
    </xsl:template>

</xsl:stylesheet>

输出

<html>
   <body>
      <p>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.<span class="noteRef" id="0001"><sup>1</sup></span></p>
      <div id="note-0001">
         <p>You may need to consult a latin butcher. Good Luck.</p>
      </div>
      <p>Pork loin 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>
   </body>
</html>
于 2012-12-11T21:01:28.687 回答
1

假设我认为使用 XSLT 2.0 处理器for-each-group会有所帮助:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  version="2.0">

<xsl:output method="html" indent="yes" version="5.0"/>

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

<xsl:template match="p[not((.//p, .//div))]">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="p[.//p, .//div]">
  <xsl:for-each-group select="node()" group-adjacent="boolean((self::text(), self::note.ref))">
    <xsl:choose>
      <xsl:when test="current-grouping-key()">
        <p>
          <xsl:apply-templates select="current()/@*, current-group()"/>
        </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}">
        <xsl:apply-templates/>
    </div>
</xsl:template>

</xsl:stylesheet>

可能需要扩展模式p[not((.//p, .//div))]和表达式以覆盖您在输入中期望p[.//p, .//div]的其他类型的节点并且需要相同的处理。group-adjacentboolean((self::text(), self::note.ref))

于 2012-12-12T13:41:55.113 回答