generic xslt to nest a xml-document as text within an element

M

Martin

Hallo,

can you help me writing a generic xslt transformation (useable with
xsql from oracle)? The problem is how to get the escaping characters
....

=== INPUT-File in.xml
<?xml version = '1.0'?>
<person><who>scott</who></person>

=== Needed OUTPUT-File out.xml
=== Note: the format must be exactly this to be
=== processable by xsql using xsql-insert
<?xml version = '1.0'?>
<ROWSET><ROW>
<NAME>&lt;person>&lt;who>scott&lt;/who>&lt;/person></NAME>
</ROW></ROWSET>

=== My xslt-File p.xsl, that misses the important fact
=== of replacing < with &lt;
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:eek:utput method="xml" omit-xml-declaration="yes"/>
<xsl:template match="@*|node()">
<xsl:element name="ROWSET">
<xsl:element name="ROW">
<xsl:element name="NAME">
<xsl:copy-of select="."/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

=== my output, that is not the expected
oraxsl in.xml p.xsl
<ROWSET><ROW><NAME><person><who>scott</who></person></NAME></ROW></ROWSET>

Any ideas?
Thank you if you find the time for helping,
Martin
 
P

Patrick TJ McPhee

% === INPUT-File in.xml
% <?xml version = '1.0'?>
% <person><who>scott</who></person>
%
% === Needed OUTPUT-File out.xml
% === Note: the format must be exactly this to be
% === processable by xsql using xsql-insert
% <?xml version = '1.0'?>
% <ROWSET><ROW>
% <NAME>&lt;person>&lt;who>scott&lt;/who>&lt;/person></NAME>
% </ROW></ROWSET>

% === My xslt-File p.xsl, that misses the important fact
% === of replacing < with &lt;
% <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
% version="1.0">
% <xsl:eek:utput method="xml" omit-xml-declaration="yes"/>
% <xsl:template match="@*|node()">
% <xsl:element name="ROWSET">
% <xsl:element name="ROW">
% <xsl:element name="NAME">
% <xsl:copy-of select="."/>
% </xsl:element>
% </xsl:element>
% </xsl:element>
% </xsl:template>
% </xsl:stylesheet>

You should keep in mind that the output of the XSLT process is a tree,
not just text. When you use copy-of, what you're doing is copying the
tree structure related to the node, not the tags themselves.


So, how do you get the tags? Probably node-by-node, using the name()
function. If all you want is a copy of the original document with
< and & escaped, I'm not sure XSLT is the best thing to use, but
let's have an untested go at it

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:eek:utput method="xml" omit-xml-declaration="yes"/>

<!-- need to handle elements, pis, comments, and attributes separately
since we need to format the tags. We start with elements -->
<xsl:template match="*">
<!-- no need for xsl:element here, so let's not use it -->
<ROWSET>
<ROW>
<NAME>
<xsl:text>&lt;</xsl:text>
<xsl:value-of select="name()"/>

<!-- attributes go here -->
<xsl:for-each select="@*">
<xsl:value-of select='name()'/.
<xsl:text>='</xsl:text>
<!-- you might need to deal with quotes here -->
<xsl:value-of select='.'/.
<xsl:text>'</xsl:text>
</xsl:for-each>
<xsl:text>&gt;</xsl:text>

<xsl:apply-templates/>

<xsl:text>&lt;/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>&gt;</xsl:text>
</NAME>
</ROW>
</ROWSET>
</xsl:template>

<xsl:template match="processing-instruction()">
<xsl:text>&lt;?</xsl:text>
<xsl:value-of select='name()'/>
<xsl:text> </xsl:text>
<xsl:value-of select='.'/>
<xsl:text>?&gt;</xsl:text>
</xsl:template>

<xsl:template match="comment()">
<xsl:text>&lt;-- </xsl:text>
<xsl:value-of select='.'/>
<xsl:text> --&gt;</xsl:text>
</xsl:template>

</xsl:stylesheet>
 
M

Martin

Hallo Patrick,

for an untested go your answer was really excellent.
I've found (after quite some more study of xsl/xpath) a solution,
but comparing it with your solution i got to know the
difference between a beginner and an expert (simply because my
solution was neither elegant, nor did I cover points like
comment-nodes or processing instructions).

A big thank you for your answer!

For other readers: see the finished solution below ...

Greetings from vienna,
Martin

===== rowset_row_doc.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" />

<xsl:template match="/">
<xsl:element name="ROWSET">
<xsl:element name="ROW">
<xsl:element name="DOC">
<xsl:apply-templates/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>

<!-- need to handle elements, pis, comments, and attributes separately
since we need to format the tags. We start with elements -->
<xsl:template match="*">
<xsl:text>&lt;</xsl:text>
<xsl:value-of select="name()"/>

<!-- attributes go here -->
<xsl:for-each select="@*">
<xsl:text> </xsl:text>
<xsl:value-of select='name()'/>
<xsl:text>="</xsl:text>
<!-- Assumption: input file has not apostrophs -->
<xsl:value-of select='.'/>
<xsl:text>"</xsl:text>
</xsl:for-each>
<xsl:text>&gt;</xsl:text>

<xsl:apply-templates/>

<xsl:text>&lt;/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>&gt;</xsl:text>
</xsl:template>

<xsl:template match="processing-instruction()">
<xsl:text>&lt;?</xsl:text>
<xsl:value-of select='name()'/>
<xsl:text> </xsl:text>
<xsl:value-of select='.'/>
<xsl:text>?&gt;</xsl:text>
</xsl:template>

<xsl:template match="comment()">
<xsl:text>&lt;-- </xsl:text>
<xsl:value-of select='.'/>
<xsl:text> --&gt;</xsl:text>
</xsl:template>

</xsl:stylesheet>
===== output from above sample
C:\XDK>oraxsl in.xml rowset_row_doc.xsl
<?xml version = '1.0'?>
<ROWSET><ROW><DOC>&lt;person>&lt;who>scott&lt;/who>&lt;/person></DOC></ROW></ROWSET>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top