This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Collecting attributes from the ancestor-or-self axis
- From: "B. Tommie Usdin" <btusdin at mulberrytech dot com>
- To: xsl-list <xsl-list at lists dot mulberrytech dot com>
- Date: Fri, 16 Nov 2001 09:36:39 -0500
- Subject: [xsl] Collecting attributes from the ancestor-or-self axis
- Reply-to: xsl-list at lists dot mulberrytech dot com
>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