Jump to content

add attribute then apply-imports


nemobluesix

Recommended Posts

Hello all,I have a general style-sheet that I'm applying to several xmls by importing it in each personalized style-sheet. In one of the personalized style-sheets I'm trying to add an attribute without success. Best explained by the code:The general style-sheet (file general.xsl):

<?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0"		xmlns:xsl="http://www.w3.org/1999/XSL/Transform">		<xsl:template match="/">				<xsl:apply-templates/>		</xsl:template>		<xsl:template match="parent">				<xsl:apply-templates/>		</xsl:template>		<xsl:template match="child">				<xsl:copy>						<xsl:copy-of select="@*"/>				</xsl:copy>		</xsl:template></xsl:stylesheet>

The personalized style-sheet (file main.xsl):

<?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0"		xmlns:xsl="http://www.w3.org/1999/XSL/Transform">		<xsl:import href="general.xsl"/>		<xsl:template match="//child[@name='bb']">				<xsl:attribute name="width">7</xsl:attribute>		</xsl:template>		<xsl:template match="/">				<xsl:apply-templates select="//child[@name='bb']"/>				<xsl:apply-imports/>		</xsl:template></xsl:stylesheet>

The xml file (file test.xml):

<root>		<parent>				<child name="aa" width="4" />				<child name="bb" />		</parent>		<parent>				<child name="cc" /> 		</parent></root>

running xsltproc main.xsl test.xml I'm expecting to get the output:

<?xml version="1.0"?>				<child name="aa" width="4"/>				<child name="bb" width="7"/>				<child name="cc"/>

but I'm getting:

<?xml version="1.0"?>				<child name="aa" width="4"/>				<child name="cc"/>

Any ideas?Thanks in advance.

Link to comment
Share on other sites

There is no way to use apply-imports the way you have set up your stylesheets. What currently happens is that the template

	   <xsl:template match="//child[@name='bb']">				<xsl:attribute name="width">7</xsl:attribute>		</xsl:template>

is applied when no element has been created but then tries to create an attribute. That is an error an XSLT processor can either report and stop processing or can ignore by not creating the attribute. The output you get indicates your XSLT processor ignores the error.As for getting the output you want, you could do that by having the main stylesheet as follows:

<xsl:stylesheet version="1.0"		xmlns:xsl="http://www.w3.org/1999/XSL/Transform">		<xsl:import href="general.xsl"/>		<xsl:template match="child[@name='bb']">		  <xsl:copy>			<xsl:copy-of select="@*"/>			<xsl:attribute name="width">7</xsl:attribute>		  </xsl:copy>		</xsl:template>		</xsl:stylesheet>

That does not use apply-imports, it simply has one template for the "child" element you want to treat differently. For any other nodes the templates in the imported stylesheet are applied.

Link to comment
Share on other sites

Thanks Martin for your reply.Obviously, I'm new to xslt and your post cleared the picture a little bit more.The thing is that I need to apply the import too. Is there a way to process the same node twice? What I'm trying to achieve is to add a new attribute before or after the general transformation has taken place. I could merge the general and the main style-sheets and modify it according to my needs but that wouldn't be either elegant nor efficient :) . Subsequent modifications would have to be made in two places. So...

Link to comment
Share on other sites

You can only add an attribute once you have already created an element node the attribute can be attached to.So in your importing stylesheet you could have e.g.

<xsl:template match="foo">  <xsl:copy>	<xsl:copy-of select="@*"/>	<xsl:apply-imports/>  </xsl:copy></xsl:template>

and then in your imported stylesheet you could have e.g.

<xsl:template match="foo">  <xsl:attribute name="bar">whatever</xsl:attribute></xsl:template>

That way the main stylesheet creates an element node and the apply-imports adds an attribute.

Link to comment
Share on other sites

I see. Sadly adding the attribute is the exception and can't be included in the imported style-sheet. I guess I'll go with the merged style-sheet solution for this particular xml (I have the option of setting different style-sheets for every xml).I always thought that the xml is read into memory and then rules are applied to it, every node being accessible all the time from all templates; so thats where the confusion started for me. As I understand now, the output (not necessarily an xml file) is created as you advance through the xml tree of nodes that have templates defined. Is this correct? Am I making any sense? :)I'm not a native English speaker and my ideas do not flow as clear as I'd like, so sorry about that.

Link to comment
Share on other sites

The processing model works on one or more input trees and creates one or more result trees that can optionally be serialized (as XML or HTML or plain text). It is true that the complete input XML is read into memory to build an input tree and you can certainly access all nodes in the input tree all the time with the various XPath axes. But you can´t create an attribute node in a result tree without having an element node to attach the attribute to.

Link to comment
Share on other sites

I think I'm starting to get the picture :). The input tree is read only and the output tree is built from it top to bottom. I assumed I can work on the input tree (ie. add attributes) and then apply more transformations on the new input tree but instead, in reality, a new tree is created.Thank you for taking the time to clear this for me, it really helped :)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...