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