OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

 


 

   RE: [xml-dev] Identiy Transform Question

[ Lists Home | Date Index | Thread Index ]

Title: Message
Thanks Micheal! That gives me just what I needed.  I'll remember to ask any further XSL questions I may have on the xsl-list.
 
Dave
 
-----Original Message-----
From: Michael Kay [mailto:michael.h.kay@ntlworld.com]
Sent: Saturday, March 23, 2002 6:58 AM
To: 'Dave Simmonds'; xml-dev@lists.xml.org
Subject: RE: [xml-dev] Identiy Transform Question

XSL coding questions are probably best asked on the xsl-list at www.mulberrytech.com (though it seems to be having some downtime today).
 
You've got the basic idea: write a template rule for all nodes that copies that node, and does xsl:apply-templates to process its children. Then write additional (higher-priority) template rules for the nodes that you don't want to copy exactly.
 

 

1)   Convert an attribute for an element into a "child" element of the element where the attribute was found:

             <element @name="somename"/>

 

             changes to

 

             <element>

                    <name>somename</name>

             </element> 

 

The rule for this is:

 

<xsl:template match="element">

  <xsl:copy>

  <xsl:for-each select="@*">

    <xsl:element name="{name()}"><xsl:value-of select="."/></xsl:element>

  </xsl:for-each> 

  <xsl:apply-templates/>

  <xsl:copy/>

</xsl:template>

 

Alternatively, you can call <xsl:apply-templates select="@*"/> and write a template rule to process attribute nodes.

 

  2)   Bring certain elements up 1 level or more levels:

              <element1>

                    <element2>

                           <element3>somedata1</element3>

                           <element4>somedata2</element4>

                    </element2>

             </element1>

 

             changes to

 

             <element1>

                    <element3>somedata1</element3>

                    <element3>somedata2</element4>

             </element1> 

 

You can do this by writing a rule for element2:

 

<xsl:template match="element2">

  <xsl:apply-templates/>

</xsl:template>

 

 

I didn't see a way to do this with the "classic" identity transform and override templates.  If there is a way, by all means let me know.

 

I actually have a transform (see below) that I believe is a good start to solving this problem, but I am running into 1 significant problem. The piece of the transform that iterates over the attributes of an element fails to see any namespace attributes.  You can run this transform against any XML document and it currently outputs the identity XML document minus and namespace attributes.  My question is why?  Or more importantly how do I get it to give me the namespace attributes so that I can output them? 

 

"Namespace attributes" don't exist in the XPath data model (or the infoset).They appear instead as namespace nodes, which are accessible via the namespace axis. You don't normally need to access namespace nodes explicitly, because if you use <xsl:copy> to copy an element, all its namespace nodes are copied too. The reason that the namespace nodes are not copied in your case is that you are doing <xsl:element name="{name()}"> rather than <xsl:copy>. You can still do this if you want; just follow it with <xsl:copy-of select="namespace::*"/>.

 

Dave Simmonds

Vantage Controls, Inc.

dsimmonds@vantagecontrols.com

 

XSL follows:

 

<?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" version="1.0" encoding="UTF-8" indent="yes"/>

 

       <!-- match all elements-->

       <xsl:template match="*">

             <xsl:element name="{name()}">

                    <xsl:for-each select="@*">   <!-iterate over each attribute - why are namespace attributes skipped? -->

                           <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>

                    </xsl:for-each>

                    <xsl:value-of select="."/>      <!-- if there is a value for this element - output it now --> 

You probably don't want the above line. The default template rule for text nodes will output the text automatically. 

             <xsl:apply-templates/>

             </xsl:element>

       </xsl:template>

      

       <!-- Copy all comments -->

       <xsl:template match="comment()">

             <xsl:copy/>

       </xsl:template>

 

       <!-- Copy all processing instructions -->

       <xsl:template match="processing-instruction()">

             <xsl:copy/>

       </xsl:template>

      

</xsl:stylesheet> 

 

Michael Kay
Software AG
home: Michael.H.Kay@ntlworld.com
work: Michael.Kay@softwareag.com

 

 

 





 

News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 2001 XML.org. This site is hosted by OASIS