Vinicius Melo
Vinicius Melo

Reputation: 161

XSLT - Trouble to filter parent nodes by its childs using a configuration node

I have some situation in XSL that I can't figure out how to resolve.

I have the following xml, and I want to show only the main nodes that have at least one item enabled by the config/enable-items nodes.

Any hints?

Thanks in advance.

xml:

<xml>

<main name="Main Section 1" id="1">
    <item id="a">
    </item>
    <item id="b">
    </item>
    <item id="c">
    </item>
</main>

<main name="Main Section 2" id="2">
    <item id="d">
    </item>
    <item id="e">
    </item>
    <item id="f">
    </item>
</main>

<config>
    <enable-items>
        <item id="a" />
        <item id="b" />
    </enable-items>
</config>

</xml>

Wanted output:

Main Section 1:
    * a
    * b

p.s.: I've tried something using key, defining a key for the enable-items indexed by the id attribute, and doing a for-each on the items to define a variable ... But with no luck, :(, I still don't know how check the items inside main before showing the main @name attribute ...

Upvotes: 2

Views: 131

Answers (2)

Florent Georges
Florent Georges

Reputation: 2327

The following:

<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="text"/>

   <xsl:template match="/input">
      <xsl:variable name="keys" select="config/enable-items/item/@id" as="xs:string+"/>
      <xsl:variable name="items" select="main/item[@id = $keys]"/>
      <xsl:for-each select="$items/..">
         <xsl:variable name="main" select="."/>
         <xsl:value-of select="@name"/>
         <xsl:text>:&#10;</xsl:text>
         <xsl:for-each select="$items intersect $main/item">
            <xsl:text>    * </xsl:text>
            <xsl:value-of select="@id"/>
            <xsl:text>&#10;</xsl:text>
         </xsl:for-each>
      </xsl:for-each>
   </xsl:template>

</xsl:stylesheet>

applied to your input (where I've changed the root element name to input, as xml is not a valid element name), produces:

Main Section 1:
    * a
    * b

If you change the second config item to e, it produces the following:

Main Section 1:
    * a
Main Section 2:
    * e

Upvotes: 1

Vinicius Melo
Vinicius Melo

Reputation: 161

Well,

I was trying it using a more complex xml, on a real world application. When I did this example to post here, I managed to get it working :)

Follow the answer:

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

<xsl:key name="enable-items" match="config/enable-items/item" use="@id"/>
<xsl:template match="/xml">
<xsl:apply-templates select="main" />  
</xsl:template>

<xsl:template match="main">
    <xsl:if test="key('enable-items', item/@id)">

        <h1><xsl:value-of select="@name"/> </h1>

                <xsl:for-each select="key('enable-items', item/@id)">
               <xsl:value-of select="@id" /> <br>

             </xsl:for-each>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions