Re: How to tranform the xml

Subject: Re: How to tranform the xml
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 9 Nov 2000 10:35:25 +0000
Sarboday,

> I have a xml file  as :
>
> <?xml version="1.0" encoding="utf-8"?>
> <node1 role="MAIN">
>     <node2  mediatype="text" >
>         <text>
>             <p> xyz</p>
>             <p> ab</p>
>         </text>
>     </node2>
> </node1>
>
> I want it to be transformed to :
>
> <?xml version="1.0" encoding="utf-8"?>
> <node1 role="MAIN">
>     <node2  mediatype="text" >
>         <text><![CDATA[ <p> xyz</p>
>             <p> ab.</p>]]>
>         </text>
>     </node2>
> </node1>

Note that this is equivalent to:

<?xml version="1.0" encoding="utf-8"?>
<node1 role="MAIN">
   <node2 mediatype="text">
      <text> &lt;p&gt; xyz&lt;/p&gt;
          &lt;p&gt; ab.&lt;/p&gt;
      </text>
   </node2>
</node1>

In other words, you're not simply wrapping the content of the text
element in a CDATA section: you have to output the escaped text.

So: you want to copy node1 and node2 nodes elements, applying
templates to their content:

<xsl:template match="node1 | node2">
   <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates />
   </xsl:copy>
</xsl:template>

When you come to the text element, you want to serialise its content
into an XML-like serialisation.  I'd use modes to control this:

<xsl:template match="text">
   <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates mode="serialise" />
   </xsl:copy>
</xsl:template>

The serialising template would look something like:

<xsl:template match="*" mode="serialise">
   <xsl:text />&lt;<xsl:value-of select="name()" />
   <xsl:for-each select="@*">
      <xsl:text> </xsl:text>
      <xsl:value-of select="name()" />="<xsl:value-of select="." />"<xsl:text />
   </xsl:for-each>
   <xsl:choose>
      <xsl:when test="* or normalize-space(.)">
         <xsl:text />&gt;<xsl:apply-templates mode="serialise" />
         <xsl:text />&lt;/<xsl:value-of select="name()" />&gt;<xsl:text />
      </xsl:when>
      <xsl:otherwise> /&gt;</xsl:otherwise>
   </xsl:choose>
</xsl:template>

If you want the content of the text element to be wrapped within a
CDATA section to make it more readable, then you can set the text
element as a CDATA section element using the xsl:output element:

<xsl:output cdata-section-elements="text" />

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread