xsl-list
[Top] [All Lists]

Re: [xsl] Is split problem a grouping problem?

2018-02-02 07:45:38
Thank you Terry for getting me started. Here is my solution:

<?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";
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output indent="yes"/>
    
    <xsl:template match="book">
        <wrapper>
            <xsl:apply-templates select="//chapter|//section"/>
        </wrapper>
    </xsl:template>
    
    <!-- each section drives out a file and picks up what it needs to have -->
    <xsl:template match="chapter|section">
        <xsl:choose>
            <!-- No children sections or with <intro> child. -->
            <xsl:when test=".[not(section)] or .[child::intro]">
                <xsl:element name="file">
                    <xsl:apply-templates select="title" mode="split"/>
                 </xsl:element>
                <!-- Recurse for sections with <intro> child. -->
                <xsl:apply-templates select="section"/>
            </xsl:when>
            <!-- Recurse to get all levels. -->
            <xsl:otherwise>
                <xsl:apply-templates select="section"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template match="title" mode="split">
        <!-- Recursively get ancestor chapter or section titles. -->
        <xsl:apply-templates 
select="parent::*/preceding-sibling::*[1][self::title]" mode="split"/>
        <xsl:copy-of select="."/>
    </xsl:template>
    
</xsl:stylesheet>

This gives me the desired output:

<?xml version="1.0" encoding="UTF-8"?>
<wrapper>
   <file>
      <title>Chapter 1</title>
   </file>
   <file>
      <title>Section 1.1</title>
   </file>
   <file>
      <title>Section 1.2</title>
   </file>
   <file>
      <title>Section 1.3</title>
      <title>Section 1.3.1</title>
   </file>
   <file>
      <title>Section 1.3.2</title>
   </file>
   <file>
      <title>Section 1.3.3</title>
   </file>
   <file>
      <title>Section 1.3.4</title>
   </file>
   <file>
      <title>Section 1.3.4.1</title>
   </file>
   <file>
      <title>Section 1.3.4.2</title>
   </file>
   <file>
      <title>Section 1.3.4.3</title>
   </file>
   <file>
      <title>Section 1.1</title>
   </file>
   <file>
      <title>Section 1.2</title>
   </file>
   <file>
      <title>Section 1.3</title>
      <title>Section 1.3.1</title>
   </file>
   <file>
      <title>Section 1.3.2</title>
   </file>
   <file>
      <title>Section 1.3.3</title>
   </file>
   <file>
      <title>Section 1.3.4</title>
   </file>
   <file>
      <title>Section 1.3.4.1</title>
   </file>
   <file>
      <title>Section 1.3.4.2</title>
   </file>
   <file>
      <title>Section 1.3.4.3</title>
   </file>
   <file>
      <title>Section 1.3</title>
      <title>Section 1.3.1</title>
   </file>
   <file>
      <title>Section 1.3.2</title>
   </file>
   <file>
      <title>Section 1.3.3</title>
   </file>
   <file>
      <title>Section 1.3.4</title>
   </file>
   <file>
      <title>Section 1.3.4.1</title>
   </file>
   <file>
      <title>Section 1.3.4.2</title>
   </file>
   <file>
      <title>Section 1.3.4.3</title>
   </file>
   <file>
      <title>Section 1.3.4.1</title>
   </file>
   <file>
      <title>Section 1.3.4.2</title>
   </file>
   <file>
      <title>Section 1.3.4.3</title>
   </file>
   <file>
      <title>Chapter 2</title>
      <title>Section 2.1</title>
      <title>Section 2.1.1</title>
   </file>
   <file>
      <title>Section 2.1.2</title>
   </file>
   <file>
      <title>Section 2.1.2.1</title>
   </file>
   <file>
      <title>Section 2.1.2.2</title>
   </file>
   <file>
      <title>Section 2.1.2.3</title>
   </file>
   <file>
      <title>Section 2.2</title>
   </file>
   <file>
      <title>Chapter 2</title>
      <title>Section 2.1</title>
      <title>Section 2.1.1</title>
   </file>
   <file>
      <title>Section 2.1.2</title>
   </file>
   <file>
      <title>Section 2.1.2.1</title>
   </file>
   <file>
      <title>Section 2.1.2.2</title>
   </file>
   <file>
      <title>Section 2.1.2.3</title>
   </file>
   <file>
      <title>Chapter 2</title>
      <title>Section 2.1</title>
      <title>Section 2.1.1</title>
   </file>
   <file>
      <title>Section 2.1.2</title>
   </file>
   <file>
      <title>Section 2.1.2.1</title>
   </file>
   <file>
      <title>Section 2.1.2.2</title>
   </file>
   <file>
      <title>Section 2.1.2.3</title>
   </file>
   <file>
      <title>Section 2.1.2.1</title>
   </file>
   <file>
      <title>Section 2.1.2.2</title>
   </file>
   <file>
      <title>Section 2.1.2.3</title>
   </file>
   <file>
      <title>Section 2.2</title>
   </file>
</wrapper>



-----Original Message-----
From: Terry Badger terry_badger(_at_)yahoo(_dot_)com 
[mailto:xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com] 
Sent: Thursday, February 01, 2018 9:13 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] Is split problem a grouping problem?

Rick, From the rules this does not look like a grouping problem but rather each 
section drives a file and get what it needs. Think this is close.
Fro
<?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"; exclude-result-prefixes="xs" 
version="2.0">
    <xsl:template match="book">
        <wrapper>
            <xsl:apply-templates select="chapter/section"/>
        </wrapper>
    </xsl:template>
    <!-- each section drives out a file and picks up what it needs to have -->
    <xsl:template match="section">
        <xsl:choose>
            <!-- has intro -->
            <xsl:when test=".[intro]">
                <xsl:element name="file">
                    <xsl:copy-of select="parent::chapter/title"/>
                    <xsl:if test="parent::section and position() = 1">
                        <xsl:copy-of select="parent::section/title"/>
                    </xsl:if>
                    <xsl:copy>
                        <xsl:copy-of select="title, intro"/>
                    </xsl:copy>
                </xsl:element>
            </xsl:when>
            <!-- no children sections -->
            <xsl:when test=".[not(section)]">
                <xsl:element name="file">
                    <xsl:if test="parent::section and position() = 1">
                        <xsl:copy-of select="parent::section/title"/>
                    </xsl:if>
                    <xsl:if test="position() = 1">
                        <xsl:copy-of select="parent::chapter/title"/>
                    </xsl:if>
                    <xsl:copy-of select="."/>
                </xsl:element>
            </xsl:when>
            <!-- recurse to get all levels -->
            <xsl:otherwise>
                <xsl:apply-templates select="section"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <!-- turn off title to output only when wanted -->
    <xsl:template match="title"/>
</xsl:stylesheet> 

RFFFFFjoosfofopqcds'jnfs'output
<?xml version="1.0" encoding="UTF-8"?>
<wrapper>
    <file>
        <title>Chapter 1</title>
        <section>
            <title>Section 1.1</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.2</title>
        </section>
    </file>
    <file>
        <title>Section 1.3</title>
        <section>
            <title>Section 1.3.1</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.3.2</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.3.3</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.3.4</title>
            <intro/>
        </section>
    </file>
    <file>
        <title>Section 2.1</title>
        <section>
            <title>Section 2.1.1</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 2.1.2</title>
            <intro/>
        </section>
    </file>
    <file>
        <section>
            <title>Section 2.2</title>
        </section>
    </file>
</wrapper>
<?xml version="1.0" encoding="UTF-8"?>
<wrapper>
    <file>
        <title>Chapter 1</title>
        <section>
            <title>Section 1.1</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.2</title>
        </section>
    </file>
    <file>
        <title>Section 1.3</title>
        <section>
            <title>Section 1.3.1</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.3.2</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.3.3</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 1.3.4</title>
            <intro/>
        </section>
    </file>
    <file>
        <title>Section 2.1</title>
        <section>
            <title>Section 2.1.1</title>
        </section>
    </file>
    <file>
        <section>
            <title>Section 2.1.2</title>
            <intro/>
        </section>
    </file>
    <file>
        <section>
            <title>Section 2.2</title>
        </section>
    </file>
</wrapper> 


Terry






On ‎Thursday‎, ‎February‎ ‎01‎, ‎2018‎ ‎03‎:‎05‎:‎49‎ ‎PM, Rick Quatro 
rick(_at_)rickquatro(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote: 





Hi, I am trying to solve a problem using XSLT 2. Here is my input:

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <chapter>
        <title>Chapter 1</title>
        <section>
            <title>Section 1.1</title>
        </section>
        <section>
            <title>Section 1.2</title>
        </section>
        <section>
            <title>Section 1.3</title>
            <section>
                <title>Section 1.3.1</title>
            </section>
            <section>
                <title>Section 1.3.2</title>
            </section>
            <section>
                <title>Section 1.3.3</title>
            </section>
            <section>
                <title>Section 1.3.4</title>
                <intro/>
                <section>
                    <title>Section 1.3.4.1</title>
                </section>
                <section>
                    <title>Section 1.3.4.2</title>
                </section>
                <section>
                    <title>Section 1.3.4.3</title>
                </section>
            </section>
        </section>
    </chapter>
    <chapter>
        <title>Chapter 2</title>
        <section>
            <title>Section 2.1</title>
            <section>
                <title>Section 2.1.1</title>
            </section>
            <section>
                <title>Section 2.1.2</title>
                <intro/>
                <section>
                    <title>Section 2.1.2.1</title>
                </section>
                <section>
                    <title>Section 2.1.2.2</title>
                </section>
                <section>
                    <title>Section 2.1.2.3</title>
                </section>
            </section>
        </section>
        <section>
            <title>Section 2.2</title>
        </section>
    </chapter>
</book>

I want to split this content up into separate files (eventually HTML). Here is 
the desired output:

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <file>
        <title>Chapter 1</title>
        <section>
            <title>Section 1.1</title>
        </section>
    </file>
    <file>
        <title>Section 1.2</title>
    </file>
    <file>
        <title>Section 1.3</title>
        <section>
            <title>Section 1.3.1</title>
        </section>
    </file>
    <file>
        <title>Section 1.3.2</title>
    </file>
    <file>
        <title>Section 1.3.3</title>
    </file>
    <file>
        <!-- Doesn't have to be with the following child section because it has 
<intro/> content. -->
        <title>Section 1.3.4</title>
        <intro/>
    </file>
    <file>
        <title>Section 1.3.4.1</title>
    </file>
    <file>
        <title>Section 1.3.4.2</title>
    </file>
    <file>
        <title>Section 1.3.4.3</title>
    </file>
    <file>
        <!-- All have to stay together because there is no content between the 
<title/> and child <section/> -->
        <title>Chapter 2</title>
        <section>
            <title>Section 2.1</title>
            <section>
                <title>Section 2.1.1</title>
            </section>
        </section>
    </file>
    <file>
        <title>Section 2.1.2</title>
        <intro/>
    </file>
    <file>
        <title>Section 2.1.2.1</title>
    </file>
    <file>
        <title>Section 2.1.2.2</title>
    </file>
    <file>
        <title>Section 2.1.2.3</title>
    </file>
    <file>
        <title>Section 2.2</title>
    </file>
</book>

The rules are as follows: A <section> can be in its own file if

1) There are no child <section> elements (like Section 1.2).
2) There is element content after the <title> and before the first child 
<section> element; for example an <intro> element (like Section 1.3.4).

Otherwise, the <section> has to contain any first child descendants (like 
Chapter 2 through Section 2.1.1).

This looks to me like a grouping problem where I can use <xsl:for-each-group>. 
I have this as a shell but I want to make sure I am on the right track. Thank 
you very much.

<?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";
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:template match="/">
        <xsl:for-each-group group-starting-with="//chapter|//section"
select=".">
            <file>
                <xsl:copy-of select="current-group()"/>
            </file>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

Rick
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>