Roy Tan
Roy Tan

Reputation: 25

Missing descendant node from XSLT

As per http://xsltfiddle.liberty-development.net/jxNakA5/1, I am missing the following descendant node in the output:

<test-child>123</test-child>

Any idea what can be wrong here?

Source XML

?xml version="1.0" encoding="UTF-8"?>
<library>
    <content content-id="a">
        <test>
            <test-child>123</test-child>
        </test>        
        <data xml:lang="x-default">{"product" : 123 }</data>    
        <content-links>
            <content-link content-id="a1"/>
            <content-link content-id="a2"/>
        </content-links>
    </content>
    <content content-id="b">
        <data xml:lang="x-default">{"product" : 123 }</data>
        <content-links>
            <content-link content-id="b1"/>
            <content-link content-id="b2"/>
        </content-links>
    </content>
    <content content-id="a1">
        <data xml:lang="x-default">{"product" : 123 }</data>
        <content-links>
            <content-link content-id="a11"/>
            <content-link content-id="a12"/>
        </content-links>
    </content>
    <content content-id="a2">
        <data xml:lang="x-default">{"product" : 123 }</data>
        <content-links>
            <content-link content-id="a21"/>
            <content-link content-id="a22"/>
        </content-links>
    </content>
    <content content-id="a11">
        <data xml:lang="x-default">{"product" : 123 }</data>
    </content>
    <content content-id="a12"/>
    <content content-id="a21">
        <data xml:lang="x-default">{"product" : 123 }</data>
    </content>
</library>

XSLT

<xsl:stylesheet 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="#all"
    version="3.0">
    
    <xsl:function name="mf:get-related-elements" as="element()*">
        <xsl:param name="element" as="element()"/>
        <xsl:sequence
            select="$element ! (. | * | key('ref', content-links/content-link/@content-id)/mf:get-related-elements(.))"/>
    </xsl:function>
    
    <xsl:key name="ref" match="/*//*" use="@content-id"/>
    
    <xsl:param name="cid" select="'a'" />
    
    <xsl:variable name="start" select="key('ref', $cid)"/>
    <xsl:variable name="related-elements" select="mf:get-related-elements($start)"/>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="/*//*[not(. intersect $related-elements)]"/>
    
</xsl:stylesheet>

Upvotes: 0

Views: 50

Answers (2)

Michael Kay
Michael Kay

Reputation: 163595

Well, it's pretty clear why it isn't being copied: it's not a "related element".

I don't know what you're trying to achieve (you haven't told us), but your code is treating children as related, but not deeper descendants. The function follows the relationship through @content-id recursively, but it doesn't recurse when selecting the children of the supplied element, so only the first-level children are selected.

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167716

See whether using

<xsl:sequence
            select="$element ! (. | .//* | key('ref', content-links/content-link/@content-id)/mf:get-related-elements(.))"/>

works for your latest requirement.

But it is hard to tell whether the original approach patched each time you add a requirement is the right way to go unless you start describing with some sentences what the criteria are to copy and not to copy nodes through to the output.

Upvotes: 1

Related Questions