This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Collecting attributes from the ancestor-or-self axis



>From: "WATKIN-JONES,ADAM (HP-UnitedKingdom,ex1)" <adam_watkin-jones@hp.com>
>To: "'xsl-list@lists.mulberrytech.com'" <xsl-list@lists.mulberrytech.com>
>Subject: Help collecting attributes from the ancestor-or-self axis
>Date: Fri, 16 Nov 2001 14:22:50 -0000
>Hello!
>
>I am trying to write some XSLT to do the following:
>
>1. start at element E
>2. add all its attributes to the output
>3. move to E's parent, EP
>4. add to the output all those attributes
>   of EP that do not have the same name as
>   as an attribute already added to the output
>5. move to EP's parent and so on collecting
>   new attributes until I've reached the last
>   ancestor of P.
>
>Below is some XML input, XML output and XSLT.
>(Actually there's a second XSLT at the end as well.)
>
>The XSLT processes the input as intended but I'm not very satisfied with it
>- it feels a bit cludgy and I'm concerned it will perform poorly on a big
>input document.
>
>Question 1
>
>The second XSLT represents an attempt to improve on the first.  The problem
>is that it requires a mysterious ingredient, possessed by very few (all
>right then, maybe possessed by many but not by me!): ?something magical?.
>
>?something magical? is some XPath that takes a node set of attributes and an
>element and it should find all the attributes of the element that do not
>have the same name as an attribute in the node set.
>
>Question 2
>Have I got the basic technique wrong?  Is there some more powerful magic out
>there?  (I tried to use the ancestor-or-self axis to construct a node set of
>all attributes of interest and then turn it into some sort of grouping
>problem but couldn't figure out how to make it work.)
>
>
>Many thanks!
>
>Adam
>
>
>
>/////////////////////////////////////////////////////////////////
>/// XML
>
><?xml version="1.0"?>
>
><elem1
>        attr0="a"
>        attr1="b"
>        attr2="c"
>        attr3="d">
>    <elem2
>            attr1="e"
>            attr3="f"
>            attr4="g"
>            attr5="h"
>            attr6="i">
>        <elem3
>                attr1="j"
>                attr2="k"
>                attr7="l"
>                attr8="m"
>                attr9="n"/>
>    </elem2>
></elem1>
>
>
>/////////////////////////////////////////////////////////////////
>/// OUTPUT (Saxon 6.4.3)
>
><?xml version="1.0" encoding="utf-8"?>
><attributes>
>   <attribute name="attr1" value="j" context="elem3"/>
>   <attribute name="attr2" value="k" context="elem3"/>
>   <attribute name="attr7" value="l" context="elem3"/>
>   <attribute name="attr8" value="m" context="elem3"/>
>   <attribute name="attr9" value="n" context="elem3"/>
>   <attribute name="attr3" value="f" context="elem2"/>
>   <attribute name="attr4" value="g" context="elem2"/>
>   <attribute name="attr5" value="h" context="elem2"/>
>   <attribute name="attr6" value="i" context="elem2"/>
>   <attribute name="attr0" value="a" context="elem1"/>
></attributes>
>
>
>/////////////////////////////////////////////////////////////////
>/// XSLT
>
><?xml version="1.0" encoding="UTF-8"?>
>
><xsl:stylesheet
>        version="1.0"
>        xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>
>    <xsl:output method="xml" indent="yes"/>
>
>
>    <xsl:template match="/">
>        <attributes>
>            <xsl:call-template name="GetAttributes">
>                <xsl:with-param name="nsAttributes" select="/.."/>
>                <xsl:with-param name="nsContext"
>select="elem1/elem2/elem3"/>
>            </xsl:call-template>
>        </attributes>
>    </xsl:template>
>
>
>    <xsl:template name="GetAttributes">
>
>        <xsl:param name="nsAttributes"/>
>        <xsl:param name="nsContext"/>
>
>        <xsl:variable name="nsNewAttributes">
>            <dummy>
>                <xsl:for-each select="$nsContext/attribute::*">
>                    <xsl:if test="count($nsAttributes/dummy/attribute/
>                            @name[. = name(current())]) = 0">
>                        <attribute name="{name()}"/>
>                    </xsl:if>
>                </xsl:for-each>
>            </dummy>
>        </xsl:variable>
>
>        <xsl:variable name="nsParent" select="$nsContext/.."/>
>
>        <xsl:for-each select="$nsContext/attribute::*">
>            <xsl:if test="0 = count($nsAttributes/dummy/attribute/
>                    @name[. = name(current())])">
>                <attribute name="{name()}" value="{.}"
>                        context="{name($nsContext)}"/>
>            </xsl:if>
>        </xsl:for-each>
>
>        <xsl:if test="$nsParent">
>            <xsl:call-template name="GetAttributes">
>                <xsl:with-param name="nsAttributes"
>                        select="$nsAttributes | $nsNewAttributes"/>
>                <xsl:with-param name="nsContext" select="$nsParent"/>
>            </xsl:call-template>
>        </xsl:if>
>
>    </xsl:template>
>
>
></xsl:stylesheet>
>
>
>/////////////////////////////////////////////////////////////////
>/// XSLT Preferred (just requires ?something magical?)
>
><?xml version="1.0" encoding="UTF-8"?>
>
><xsl:stylesheet
>        version="1.0"
>        xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>
>    <xsl:output method="xml" indent="yes"/>
>
>
>    <xsl:template match="/">
>        <attributes>
>            <xsl:call-template name="GetAttributes">
>                <xsl:with-param name="nsAttributes" select="/.."/>
>                <xsl:with-param name="nsContext"
>select="elem1/elem2/elem3"/>
>            </xsl:call-template>
>        </attributes>
>    </xsl:template>
>
>
>    <xsl:template name="GetAttributes">
>
>        <xsl:param name="nsAttributes"/>
>        <xsl:param name="nsContext"/>
>
>        <xsl:variable name="nsNewAttributes" select="?something magical?">
>
>        <xsl:variable name="nsParent" select="$nsContext/.."/>
>
>        <xsl:for-each select="$nsNewAttributes">
>            <attribute name="{name()}" value="{.}"
>                    context="{name($nsContext)}"/>
>        </xsl:for-each>
>
>        <xsl:if test="$nsParent">
>            <xsl:call-template name="GetAttributes">
>                <xsl:with-param name="nsAttributes"
>                        select="$nsAttributes | $nsNewAttributes"/>
>                <xsl:with-param name="nsContext" select="$nsParent"/>
>            </xsl:call-template>
>        </xsl:if>
>
>    </xsl:template>
>
>
></xsl:stylesheet>



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]