[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Using XPath to match two node levels with the same name


Subject: Re: [xsl] Using XPath to match two node levels with the same name
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Mon, 7 Aug 2006 21:10:09 +0530

Please try this stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:redirect="http://xml.apache.org/xalan/redirect"

extension-element-prefixes="redirect">

<xsl:output method="xml" />

<xsl:template match="/">
 <xsl:apply-templates select="topic" />
 <xsl:apply-templates select="//topic[count(ancestor::topic) = 1]" />
</xsl:template>

<xsl:template match="topic">
 <xsl:variable name="filename" select="concat(@id,'.xml')"/>
 <redirect:write select="$filename">
   <topic>
     <xsl:copy-of select="@*" />
     <xsl:apply-templates mode="x"/>
   </topic>
 </redirect:write>
</xsl:template>

<xsl:template match="topic[count(ancestor::topic) = 1]">
 <xsl:variable name="filename" select="concat(@id,'.xml')"/>
 <redirect:write select="$filename">
   <xsl:copy-of select="." />
 </redirect:write>
</xsl:template>

<xsl:template match="*" mode="x">
 <xsl:if test="not(self::topic)">
   <xsl:copy>
     <xsl:copy-of select="@*" />
     <xsl:apply-templates mode="x" />
   </xsl:copy>
 </xsl:if>
</xsl:template>

</xsl:stylesheet>

This when applied to XML:

<topic id="1">
 <title>Root level</title>
 <prolog/>
 <body>
   <p>This is the root-level topic.</p>
 </body>
 <topic id="2a">
   <title>Child level 2a</title>
   <prolog/>
   <body>
     <p>This is child level 2a.</p>
   </body>
   <topic id="3a">
     <title>Child level 3a</title>
     <prolog/>
     <body>
       <p>This is child level 3a.</p>
     </body>
   </topic>
 </topic>
 <topic id="2b">
   <title>Child level 2b</title>
   <prolog/>
     <body>
      <p>This is child level 2b.</p>
     </body>
     <topic id="3b">
       <title>Child level 3b</title>
       <prolog/>
       <body>
         <p>This is child level 3b.</p>
       </body>
     </topic>
     <topic id="3c">
       <title>Child level 3c</title>
       <prolog/>
       <body>
         <p>This is child level 3c.</p>
       </body>
     </topic>
 </topic>
</topic>

Produces 3 output files:

1.xml

<?xml version="1.0" encoding="UTF-8"?>
<topic id="1">
 <title>Root level</title>
 <prolog/>
 <body>
   <p>This is the root-level topic.</p>
 </body>
</topic>

2a.xml

<?xml version="1.0" encoding="UTF-8"?>
<topic id="2a">
   <title>Child level 2a</title>
   <prolog/>
   <body>
     <p>This is child level 2a.</p>
   </body>
   <topic id="3a">
     <title>Child level 3a</title>
     <prolog/>
     <body>
       <p>This is child level 3a.</p>
     </body>
   </topic>
</topic>

2b.xml

<?xml version="1.0" encoding="UTF-8"?>
<topic id="2b">
   <title>Child level 2b</title>
   <prolog/>
     <body>
      <p>This is child level 2b.</p>
     </body>
     <topic id="3b">
       <title>Child level 3b</title>
       <prolog/>
       <body>
         <p>This is child level 3b.</p>
       </body>
     </topic>
     <topic id="3c">
       <title>Child level 3c</title>
       <prolog/>
       <body>
         <p>This is child level 3c.</p>
       </body>
     </topic>
</topic>

Hope this helps.

--
Regards,
Mukul Gandhi

http://gandhimukul.tripod.com

On 8/7/06, Mark Peters <flickrmeister@xxxxxxxxx> wrote:
Hi guys,

I'm trying to split a set of nested <topic> elements into separate XML
files using the Xalan redirect extension. My input XML document could
contain as many as four levels of <topic> elements, with <topic> being
the root-level node. My plan is to split the root-level <topic> into
its own file (without including any child <topic>s). The first level
of child <topic>s would also get their own files. This set of files
would include any nested <topic> elements.

My plan is to split a chapter of technical documentation containing
nested topics into a separate files containing the chapter-level
(overview) topic file and the major heading topics.

Can I match the two desired levels of <topic> elements using XPath?
I'm guessing I could use match="root" to express the top
(chapter-level) node. But I'm having some trouble wrapping my mind
around the XPath processing flow ("contains"?  "ancestor"?
"following-sibling"?) to formulate a match for my highest child
<topic> elements.


This is my input XML:


<topic id="1">
       <title>Root level</title>
       <prolog/>
       <body>
               <p>This is the root-level topic.</p>
       </body>
       <topic id="2a">
               <title>Child level 2a</title>
               <prolog/>
               <body>
                       <p>This is child level 2a.</p>
               </body>
               <topic id="3a">
                       <title>Child level 3a</title>
                       <prolog/>
                       <body>
                               <p>This is child level 3a.</p>
                       </body>
               </topic>
       </topic>
       <topic id="2b">
               <title>Child level 2b</title>
               <prolog/>
               <body>
                       <p>This is child level 2b.</p>
               </body>
               <topic id="3b">
                       <title>Child level 3b</title>
                       <prolog/>
                       <body>
                               <p>This is child level 3b.</p>
                       </body>
               </topic>
               <topic id="3c">
                       <title>Child level 3c</title>
                       <prolog/>
                       <body>
                               <p>This is child level 3c.</p>
                       </body>
               </topic>
       </topic>
</topic>


This is my desired output XML (3 separate XML files):



File 1:


<topic id="1">
       <title>Root level</title>
       <prolog/>
       <body>
               <p>This is the root-level topic.</p>
       </body>
</topic>


File 2:


<topic id="2a">
       <title>Child level 2a</title>
       <prolog/>
       <body>
               <p>This is child level 2a.</p>
       </body>
       <topic id="3a">
               <title>Child level 3a</title>
               <prolog/>
               <body>
                       <p>This is child level 3a.</p>
               </body>
       </topic>
</topic>


File 3:


<topic id="2b">
       <title>Child level 2b</title>
       <prolog/>
       <body>
               <p>This is child level 2b.</p>
       </body>
       <topic id="3b">
               <title>Child level 3b</title>
               <prolog/>
               <body>
                       <p>This is child level 3b.</p>
               </body>
       </topic>
       <topic id="3c">
               <title>Child level 3c</title>
               <prolog/>
               <body>
                       <p>This is child level 3c.</p>
               </body>
       </topic>
</topic>


This is my XSL stylesheet draft:


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:redirect="http://xml.apache.org/xalan/redirect"
extension-element-prefixes="redirect" version="1.0">
       <xsl:output method="xml"/>

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

       <xsl:template match="root">
               <xsl:variable name="filename" select="concat(@id,'.xml')"/>
               <redirect:write select="$filename">
                       <topic id="{@id}">
                               <xsl:apply-templates/>
                       </topic>
               </redirect:write>
       </xsl:template>

       <xsl:template match="topic[???]">
               <xsl:variable name="filename" select="concat(@id,'.xml')"/>
               <redirect:write select="$filename">
                       <topic id="{@id}">
                               <xsl:apply-templates/>
                       </topic>
               </redirect:write>
       </xsl:template>
       <xsl:template match="title">
               <xsl:copy-of select="."/>
       </xsl:template>
       <xsl:template match="prolog">
               <xsl:copy-of select="."/>
       </xsl:template>
       <xsl:template match="body">
               <xsl:copy-of select="."/>
       </xsl:template>
</xsl:stylesheet>


Any help would be greatly appreciated.


Regards,
Mark


--


Mark Peters
Senior Technical Writer
Saba Software


Current Thread
Keywords