Subject: RE: [xsl] Specify/determine element's "logical" parent From: "Michael Kay" <mike@xxxxxxxxxxxx> Date: Fri, 24 Sep 2004 00:16:10 +0100 |
... surprised and frustrated at how > difficult and complicated it seems for a beginner I am always frustrated at how long it takes to get to grips with a new technology, but I am never surprised by it. It's what you should expect; and the more powerful the technology, the steeper the learning curve is likely to be. > I think I need to take a few weeks off and > research XSL but I have deliverables. The problem is that you're trying to run before you have learned to walk. There are no short-cuts; learning new skills takes time. > > For instance, I do not understand the difference between the > two templates > listed below, which seem equivalent to me. The first one > fails ("Reference to > variable or parameter 'parent' must evaluate to a node list") > while the second > works. Nor do I understand why when both templates are in a single > stylesheet, only one (the latter?) seems to get applied. Any help or > suggestions would be appreciated - hopefully I am doing > something really > stupid and obvious (at least I got rid of xsl:for-each!). The way you use xsl:variable in the first example, you are creating a new XML document whose content is a copy of some of the content in your source document. That new document does not have an id attribute (in fact, documents never have attributes, only elements have attributes). What you are trying to do is to set the variable to be a reference to a node in the source document. In XSLT 2.0 you can do this using the expression: <xsl:variable name="parent" select="if (@parentid) then key( 'ids', @parentid ) else key( 'ids', ../@id )"/> It's trickier in XSLT 1.0 because XPath 1.0 doesn't have conditional expressions: but if you want a variable to be a reference to an existing node, rather than a newly constructed node containing a copy of the data, you need to use the "select" attribute. In this case there's a workaround. The @parentid attribute, if it exists, will always be after the ../@id attribute in document order. So the expression (../@id | @parentid) [last()] will select the @parentid attribute if it exists, and the ../@id attribute otherwise. So you can write: <xsl:variable name="parent" select="key('ids', (../@id | @parentid) [last()])"/> I'm afraid that XSLT coding, especially in 1.0, is full of such tricks, and there's no way to learn them except by experience. Michael Kay http://www.saxonica.com/ > > <?xml version="1.0" encoding="ISO-8859-1"?> > <xsl:stylesheet version="1.0" > xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> > <xsl:key name="ids" match="item" use="@id"/> > > <xsl:template match="/"> > <html> > <body> > <xsl:apply-templates select="/*//item"/> > </body> > </html> > </xsl:template> > > <xsl:template match="item"> > <xsl:if test="../@id"> > <xsl:variable name="parent"> > <xsl:choose> > <xsl:when test="@parentid"> > <!-- following line differs --> > <xsl:value-of select="key( 'ids', @parentid )" /> > </xsl:when> > <xsl:otherwise> > <!-- following line differs --> > <xsl:value-of select="key( 'ids', ../@id )" /> > </xsl:otherwise> > </xsl:choose> > </xsl:variable> > <!-- following line differs --> > <xsl:value-of select="@id" /> is [<xsl:value-of > select="$parent/@id" />]<br /> > </xsl:if> > </xsl:template> > > <xsl:template match="item"> > <xsl:if test="../@id"> > <xsl:variable name="parent"> > <xsl:choose> > <xsl:when test="@parentid"> > <xsl:value-of select="key( 'ids', @parentid )/@id" /> > </xsl:when> > <xsl:otherwise> > <xsl:value-of select="key( 'ids', ../@id )/@id" /> > </xsl:otherwise> > </xsl:choose> > </xsl:variable> > <xsl:value-of select="@id" /> is [<xsl:value-of > select="$parent" />]<br /> > </xsl:if> > </xsl:template> > </xsl:stylesheet> > > <?xml-stylesheet type="text/xsl" href="data.xsl"?> > <items> > <item id="A1"> > <item id="A2"> > <item id="A3" /> > </item> > </item> > <item id="B1"> > <item id="B2"> > <item id="B3" parentid="A2" /> > </item> > </item> > </items>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Specify/determine element, Robert Koberg | Thread | Re: [xsl] Specify/determine element, Joseph Dane |
Re: [xsl] R: [xsl] [text nodes] Unm, Francesco Barresi | Date | Re: [xsl] Specify/determine element, Joseph Dane |
Month |