Morten Dvinge
Morten Dvinge

Reputation: 46

XSLT (1.0) How to preserve html tags when wrapping element value in a CDATA tag

I have an XML with Text elements that can include tagged text and depending on the elements attribute value i know if the content is CDATA encapsulated or XHTML.

As i cannot have/create any child elements in the Text element i will need to encapsulate if i get XHTML.

This is just 1 of many elements i need to transform in my XSLT

A short xml sample

  <ONIXMessage release="3.0" xmlns="http://ns.editeur.org/onix/3.0/reference">
  <Product>
    <CollateralDetail>
      <TextContent>
        <Text textformat="05">
          <p>Requires internet connection for purchase, plus iPod or other Audible-compatible player or iTunes software on Mac OS X or Windows</p>
        </Text>
      </TextContent>
    </CollateralDetail>
  </Product>
  <Product>
    <CollateralDetail>
      <TextContent>
        <Text textformat="02"><![CDATA["Nogle dyr er farlige. Nogle dyr kan slå dig ihjel!"
Hvis det stod til Claras mor, var Clara aldrig blevet vildheks. Hun er bange for at Clara skal komme noget til, og det viser sig at der er en god grund. Den vilde verden ER et farligt sted – ikke mindst nu hvor Bravita Blodsunge er ved at bryde fri af det fængsel der har holdt hende fanget i 400 år ...

"Blodsungen" er fjerde bog i serien om Clara, hendes kærlighed til dyr og hendes kamp for at overleve som vildheks i en verden hvor magi ikke ligefrem er barnemad.]]></Text>
      </TextContent>
    </CollateralDetail>
  </Product>
</ONIXMessage>

I finally tried this and it does somehow achieve the goal. It is just that html tags are not preserved.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
 xmlns:onix="http://ns.editeur.org/onix/3.0/reference"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl onix xsi">

    <xsl:output method="xml" indent="no" omit-xml-declaration="yes" />
<!--  cdata-section-elements="onix:BiographicalNote onix:Text" -->
    <xsl:template match="@* | node() ">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//onix:TextContent/onix:Text ">
        <xsl:choose>
            <xsl:when test="//onix:TextContent/onix:Text/@textformat='05'">
                <xsl:element name="Text" xmlns="http://ns.editeur.org/onix/3.0/reference" >
                <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
                    <xsl:value-of select="current()"/>
                <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="current()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

This will produce the following (note the

tag is gone in the first text)

<ONIXMessage release="3.0" xmlns="http://ns.editeur.org/onix/3.0/reference">
  <Product>
    <CollateralDetail>
      <TextContent>
        <TextType>11</TextType>
        <ContentAudience>02</ContentAudience>
        <Text><![CDATA[
          Requires internet connection for purchase, plus iPod or other Audible-compatible player or iTunes software on Mac OS X or Windows
        ]]></Text>
      </TextContent>
    </CollateralDetail>
  </Product>
  <Product>
    <CollateralDetail>
      <TextContent>
        <TextType>03</TextType>
        <ContentAudience>00</ContentAudience>
        <Text><![CDATA["Nogle dyr er farlige. Nogle dyr kan slå dig ihjel!"
Hvis det stod til Claras mor, var Clara aldrig blevet vildheks. Hun er bange for at Clara skal komme noget til, og det viser sig at der er en god grund. Den vilde verden ER et farligt sted – ikke mindst nu hvor Bravita Blodsunge er ved at bryde fri af det fængsel der har holdt hende fanget i 400 år ...

"Blodsungen" er fjerde bog i serien om Clara, hendes kærlighed til dyr og hendes kamp for at overleve som vildheks i en verden hvor magi ikke ligefrem er barnemad.]]></Text>
      </TextContent>
    </CollateralDetail>
  </Product>
</ONIXMessage>

I have also tried to use cdata-section-elements="onix:Text"

But the output becomes really odd with multiple cdata tags in the output for 1 element and the only thing it doesn't encapsulate is actually the text i want to encapsulate

<BiographicalNote textformat="05"><![CDATA[
  ]]><p>A crime writer for over thirty years, Ruth Rendell has won one Crime Writers’ Association Silver Dagger Award, two Gold Daggers and, the supreme accolade, the Crime Writers’ Diamond Award for her outstanding contribution to the genre.</p><![CDATA[
]]></BiographicalNote>

How do i solve what i need to achieve? Why are the html tags removed from the element value when i try to encapsulate the text in the code i did (.. and is that even the right approach ?!)

Upvotes: 1

Views: 545

Answers (1)

Morten Dvinge
Morten Dvinge

Reputation: 46

Thank you Tim C https://stackoverflow.com/users/7585/tim-c

It seemed that i didn't fully understand the nature of value-of The solution was pretty close.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
 xmlns:onix="http://ns.editeur.org/onix/3.0/reference"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl onix xsi">

    <xsl:output method="xml" indent="no" omit-xml-declaration="yes" />
<!--  cdata-section-elements="onix:BiographicalNote onix:Text" -->
    <xsl:template match="@* | node() ">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//onix:TextContent/onix:Text ">
        <xsl:choose>
            <xsl:when test="//onix:TextContent/onix:Text/@textformat='05'">
                <xsl:element name="Text" xmlns="http://ns.editeur.org/onix/3.0/reference" >
                <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
                    <xsl:copy-of select="node()"/>
                <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="current()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions