XSL: Error when trying to copy node and attributes again for output xml

I'm using Visual studios to debug an xsl file with a given xml
I'm simply copying the entire node alongside it's attributes.

But i keep getting this error "Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added."



<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="UTF-8"/>

This is the xsl
  <xsl:template match="Fare">
    <Fare>
       		<xsl:copy-of select="./@*"/>
					<xsl:for-each select="./*">
                                              <xsl:copy-of select="."/>
					     <xsl:copy-of select="./@*"/>			<!--If I comment this line it works, but why?-->	
					</xsl:for-each>
		</Fare>			
    </xsl:template>
</xsl:stylesheet>

Open in new window



and the input file
<Fare FareType="PUBL" TravelerCount="1" TotalPrice="17968" FareNumber="1" Source="RT" SourceRef="XXYZ">
	<CurrencyCode NumberOfDecimals="2">USD</CurrencyCode>
	<Trav TypeRequested="ADT" TypePriced="ADT" TypeCount="1" TypeTotalPrice="17968">
		<Price Total="17968">
			<Base Amount="12200"/>
			<Taxes Amount="5768">
				<Tax Amount="712">
					<Designator>US</Designator>
				</Tax>
			</Taxes>
		</Price>
	</Trav>
</Fare>

Open in new window

badtz7229Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

zc2Commented:
You are copying attributes ( @* ) but there is no output element you to can append the attributes to.

In XSLT there are two "copy" directives: <xsl:copy> and <xsl:copy-to>.
The first one creates an empty element, in which you could add additional attributes and/or children.
And in your case, <xsl:copy> probably more suitable. I can not tell exactly, because I don't know what output XML structure you want to get in the result.
Check out this code:
<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="UTF-8"/>

  <xsl:template match="Fare">
    <Fare>
       		<xsl:copy-of select="./@*"/>
			<xsl:for-each select="./*">
                         <xsl:copy>
			        <xsl:copy-of select="./@*"/>	<!--No more errors-->	
                         </xsl:copy>    
			</xsl:for-each>
	</Fare>			
    </xsl:template>
</xsl:stylesheet>
                                  

Open in new window

badtz7229Author Commented:
@zc2 - if i use ur xsl it does not copy the inner nodes (price)
zc2Commented:
Copy the inner nodes using <xsl:copy-of select="*"/>

<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="UTF-8"/>

<xsl:template match="Fare">
    <Fare>
   		<xsl:copy-of select="./@*"/>
		<xsl:for-each select="./*">
             <xsl:copy>
		        <xsl:copy-of select="./@*"/>
                <xsl:copy-of select="*"/> 
             </xsl:copy>    
		</xsl:for-each>
	</Fare>			
</xsl:template>
</xsl:stylesheet>

Open in new window

Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

badtz7229Author Commented:
@zc2:

your solution does not include the   value inside CurrencyCode
it only copies attributes but not value of node itself
badtz7229Author Commented:
so my original question remains, why is it when i commented out that line in code it works but with it active it fails?
zc2Commented:
Please replace the line 11 with the following:
<xsl:copy-of select="*|text()"/>
zc2Commented:
In your original XSL, this statement
<xsl:copy-of select="./@*"/>
copies all the current input node attributes to the current output node.
The attributes have to be added to the output element before all other children are added.
Once you added a child node such as a child element or an inner text node you can not add attributes anymore.

For an instance, your XSL has two such statements, at the line 8 and the line 11.
The one at the line 8 works, because there is an active output element ( <Fare> ) and it is being declared and no children were added yet.
The one at the line 11 does not work, because you add children on the line 10 and attributes can not be added to the current output element (still <Fare> ) anymore.

Hope my explanation is understandable.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
badtz7229Author Commented:
@zc2 - thanks that worked and i understand
zc2Commented:
You are welcome
badtz7229Author Commented:
thanks
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
CSS

From novice to tech pro — start learning today.