Question

I got several XML -elements referring to eachother using a "parent" subelement. Not all toplevel -elements need copying, so I have a fixed list of (main-)section uniqueNames which do need to be copied.

List of mainsections of which subsections should be copied in my XSL:

<xsl:variable name="mainSections">|news|sport|</xsl:variable>

Source XML Main sections:

<section uniqueName="news">
</section>

<section uniqueName="sport">
</section>

<section uniqueName="travel">
</section>

Source XML Sub sections:

<section uniqueName="national_news">
  <parent uniqueName="news"/>
</section>

<section uniqueName="regional_news">
  <parent uniqueName="national_news"/>
</section>

<section uniqueName="city_news">
  <parent uniqueName="regional_news"/>
</section>

<section uniqueName="travel_europe">
  <parent uniqueName="travel"/>
</section>

<section uniqueName="holland">
  <parent uniqueName="travel_europe"/>
</section>

Etc.

Because the subsections are prone to moving, changing or deletion between development-phase and production of my XSL, I need to determine dynamically if any given subsection is a child of one of the main sections. There are also countless subsections in total. Hardcoding a list of subsections to copy is undoable.

Subsection depth can be really deep, as shown in the example: Section "city_news" has "regional_news" as parent, which has "national_news" as parent which has "news" as parent, so this section needs copying, because it is eventually a child of "news". The toplevel section "Travel" for section "holland" (under subsection "travel_europe") is not on the list to be copied, so it needs to be ignored.

At first I tried checking each element if the parent is in the list, but that was just stupid, it only gets me 1 level deep. My last attempt was to create a javascript first indexing all sections, then analyzing the structure eliminating all sections related to mainsections not on the list. But calling the script proved to be a challenge as well, since XSL has no means of its own to call javascript.

I am a bit clueless on how to proceed on this... Any solutions or suggestions?

The source XML document is 3500 lines and the info in there does not matter for this question. The question is how do I filter out subsections of subsections of subsections of a mainsection, or: How do I determine if a subsection is a child of on of the specified main-sections a few steps up the tree. Consider the 5 mentioned subsections to be input, then the output should be:

<section uniqueName="national_news">
  <parent uniqueName="news"/>
</section>

<section uniqueName="regional_news">
  <parent uniqueName="national_news"/>
</section>

<section uniqueName="city_news">
  <parent uniqueName="regional_news"/>
</section>

Since

<section uniqueName="travel_europe">
  <parent uniqueName="travel"/>
</section>

<section uniqueName="holland">
  <parent uniqueName="travel_europe"/>
</section>

relate to the "travel" main-section, which is not on the list to be copied.

Was it helpful?

Solution

This transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="pWanted" select="'|news|sport|'"/>

 <xsl:key name="kChildren" match="section" use="parent/@uniqueName"/>

 <xsl:template match="/*">
     <xsl:call-template name="getSections">
       <xsl:with-param name="pParents" select=
       "section[contains($pWanted, concat('|',@uniqueName, '|'))]"/>
     </xsl:call-template>
 </xsl:template>

 <xsl:template name="getSections">
  <xsl:param name="pParents" select="/.."/>

  <xsl:if test="$pParents">
    <xsl:copy-of select="$pParents"/>
    <xsl:call-template name="getSections">
     <xsl:with-param name="pParents"
        select="key('kChildren', $pParents/@uniqueName)"/>
    </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

when applied to the following XML document (no such was provided!!!):

<t>
    <section uniqueName="news"></section>
    <section uniqueName="sport"></section>
    <section uniqueName="travel"></section>
    <section uniqueName="national_news">
        <parent uniqueName="news"/>
    </section>
    <section uniqueName="regional_news">
        <parent uniqueName="national_news"/>
    </section>
    <section uniqueName="city_news">
        <parent uniqueName="regional_news"/>
    </section>
    <section uniqueName="travel_europe">
        <parent uniqueName="travel"/>
    </section>
    <section uniqueName="holland">
        <parent uniqueName="travel_europe"/>
    </section>
</t>

produces the wanted (not exactly specified in the question!!!), correct result:

<section uniqueName="news"/>
<section uniqueName="sport"/>
<section uniqueName="national_news">
   <parent uniqueName="news"/>
</section>
<section uniqueName="regional_news">
   <parent uniqueName="national_news"/>
</section>
<section uniqueName="city_news">
   <parent uniqueName="regional_news"/>
</section>

Explanation:

Proper use of keys and recursion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top