2016-11-17 6 views
0

Я стараюсь группировать элементы по их заголовкам. Мое текущее решение имеет один недостаток. Следующий заголовок и его содержимое вложены в тег тела предшественника. Можно ли вложить только теги в теге тела, а не в следующую группу? У кого-нибудь есть идея или предложение? Он должен выглядеть как пример желаемого результата.Вложенные группированные заголовки

Источник

<?xml version="1.0" encoding="UTF-8"?> 
<html> 
<title>headline</title> 
<body> 
    <h1 name="d1e25">H1</h1> 
    <p>p</p> 
    <h2 name="d1e25">H2</h2> 
    <p>p</p> 
    <h3 name="d1e25">H3</h3> 
    <p>p</p> 
    <h3 name="d1e25">H3</h3> 
    <p>p</p> 
    <h4 name="d1e25">H4</h4> 
    <p>p</p> 
    <h2 name="d1e25">H2</h2> 
    <table></table> 
    </body> 
</html> 

Мой curent Трансформация

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

    <xsl:output method="xml" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 

    <xsl:function name="mf:group" as="node()*"> 
    <xsl:param name="elements" as="element()*"/> 
    <xsl:param name="level" as="xs:integer"/> 
    <xsl:for-each-group select="$elements" group-starting-with="*[local-name() eq concat('h', $level)]"> 
     <xsl:choose> 
     <xsl:when test="self::*[local-name() eq concat('h', $level)]"> 
      <topic> 
      <xsl:attribute name="id"><xsl:copy-of select="@name"/></xsl:attribute> 
      <xsl:element name="title"><xsl:value-of select="." /></xsl:element> 
      <body> 
       <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/> 
      </body> 
      </topic> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="current-group()"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each-group> 
    </xsl:function> 

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

    <xsl:template match="/html"> 
    <topic> 
    <xsl:attribute name="id"> 
     <xsl:attribute name="id" select="generate-id()" /> 
    </xsl:attribute> 
     <xsl:copy-of select="title"/> 
    <xsl:apply-templates select="body"/> 
    </topic> 
    </xsl:template> 

    <xsl:template match="body"> 
    <xsl:sequence select="mf:group(*, 1)"/> 
    </xsl:template> 

</xsl:transform> 

Я получаю это из следующего после grouping following-siblings with same name and same attributes causes exception in saxon

Мой curent Результат

<topic id="d1e1"> 
    <title>headline</title> 
    <topic id="d1e25"> 
     <title>H1</title> 
     <body> 
     <p>p</p> 
     <topic id="d1e25"> 
      <title>H2</title> 
      <body> 
       <p>p</p> 
       <topic id="d1e25"> 
        <title>H3</title> 
        <body> 
        <p>p</p> 
        </body> 
       </topic> 
       <topic id="d1e25"> 
        <title>H3</title> 
        <body> 
        <p>p</p> 
        <topic id="d1e25"> 
         <title>H4</title> 
         <body> 
          <p>p</p> 
         </body> 
        </topic> 
        </body> 
       </topic> 
      </body> 
     </topic> 
     <topic id="d1e25"> 
      <title>H2</title> 
      <body> 
       <table/> 
      </body> 
     </topic> 
     </body> 
    </topic> 
</topic> 

Желаемая Result

<topic id="d1e1"> 
    <title>headline</title> 
    <topic id="d1e25"> 
     <title>H1</title> 
     <body> 
     <p>p</p> 
     <topic id="d1e25"> 
      <title>H2</title> 
      <body> 
       <p>p</p> 
       <topic id="d1e25"> 
        <title>H3</title> 
        <body> 
        <p>p</p> 
        </body> 
       </topic> 
       <topic id="d1e25"> 
        <title>H3</title> 
        <body> 
        <p>p</p> 
        <topic id="d1e25"> 
         <title>H4</title> 
         <body> 
          <p>p</p> 
         </body> 
        </topic> 
        </body> 
       </topic> 
      </body> 
     </topic> 
     <topic id="d1e25"> 
      <title>H2</title> 
      <body> 
       <table/> 
      </body> 
     </topic> 
     </body> 
    </topic> 
</topic> 

ответ

0

У меня есть решение

Моя трансформация

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

    <xsl:output method="xml" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 

<xsl:strip-space elements="*"/> 

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

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

<xsl:key name="next-headings" match="h6" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3 or self::h4 or 
               self::h5][1])" /> 
<xsl:key name="next-headings" match="h5" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3 or self::h4][1])" /> 
<xsl:key name="next-headings" match="h4" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3][1])" /> 
<xsl:key name="next-headings" match="h3" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2][1])" /> 
<xsl:key name="next-headings" match="h2" 
      use="generate-id(preceding-sibling::h1[1])" /> 

<xsl:key name="immediate-nodes" 
      match="node()[not(self::h1 | self::h2 | self::h3 | self::h4 | 
          self::h5 | self::h6)]" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3 or self::h4 or 
               self::h5 or self::h6][1])" /> 

<xsl:template match="h1 | h2 | h3 | h4 | h5 | h6"> 
    <xsl:variable name="vLevel" select="substring-after(name(), 'h')" /> 
    <topic> 
     <xsl:element name="title"> 
     <xsl:apply-templates /> 
     </xsl:element> 
     <body> 
     <xsl:apply-templates select="key('immediate-nodes', generate-id())" /> 
     </body> 
     <xsl:apply-templates select="key('next-headings', generate-id())" /> 
    </topic> 
</xsl:template> 

<xsl:template match="/*/*/node()" priority="-20"> 
    <xsl:copy-of select="." /> 
</xsl:template> 

</xsl:transform> 

Результат

<document> 
    <topic> 
     <title>H1</title> 
     <body> 
     <p>p</p> 
     </body> 
     <topic> 
     <title>H2</title> 
     <body> 
      <p>p</p> 
     </body> 
     <topic> 
      <title>H3</title> 
      <body> 
       <p>p</p> 
      </body> 
     </topic> 
     <topic> 
      <title>H3</title> 
      <body> 
       <p>p</p> 
      </body> 
      <topic> 
       <title>H4</title> 
       <body> 
        <p>p</p> 
       </body> 
      </topic> 
     </topic> 
     </topic> 
     <topic> 
     <title>H2</title> 
     <body> 
      <table/> 
     </body> 
     </topic> 
    </topic> 
</document>