Click here to Skip to main content
Click here to Skip to main content

Creating a Node Tree Fragment in XSLT Using Internet Explorer

By , 19 May 2006
 

Before transformation

Image A - Before transformation

After Transformation

Image B - After transformation

Introduction

This article describes a means of using C# to create a node-tree-fragment in XSLT.

Overview

The concept derives from embedding well-formed XML inside an existing XML object programmatically, by setting the inner text portion of a given element. I could have used an XML DOM append child node technique, but for the purposes of this example, I chose not to. When you do this, the embedded well-formed XML is treated as a string, not as XML nodes. Image A shows the embedded XML in black color. You cannot expand or collapse any of the embedded XML nodes. Several solutions that I have found required me to use a different XML parser other than what is provided via Microsoft - Xerces comes to mind. In fact, the Microsoft XML parser does not include a native function for converting strings to node-tree-fragments.

So, how can you access the values or the elements? A conversion of the XML string to a node tree fragment needs to take place.

The problem: I needed to embed XML within XML. Afterwards, a transformation from one XML format to another is performed. Embedding XML within XML is a practice not recommended by various XML pundits. However, when the situation cannot be modified such that a best-practices approach can occur, there is not a whole lot one can do. Enter IE XML/XSLT node-tree-fragment creation using the .NET Framework!

Using the code

The real trick is setting up the XSLT file with the appropriate namespaces:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:ms="urn:schemas-microsoft-com:xslt" 
 xmlns:cs="urn:the-xml-files:xslt-csharp"
 exclude-result-prefixes="cs ms">

Once the namespace declarations have been set, adding any number of .NET Framework aware classes is relatively easy. I use the XPathNodeIterator function to convert the well-formed XML string to a node-tree-fragment.

<ms:script language="C#" implements-prefix="cs">
<![CDATA[

XPathNodeIterator parse(String strXML)
{
    System.IO.StringReader rdr = new System.IO.StringReader(strXML);
    XPathDocument doc = new XPathDocument(rdr);
    XPathNavigator nav = doc.CreateNavigator();

    XPathExpression expr; 
    expr = nav.Compile("/"); 

    XPathNodeIterator iterator = nav.Select(expr);

    return iterator;
}

]]>
</ms:script>

Here is a sample XML snippet. Note the <system_codes> element. Contained within, I programmatically embed a well-formed XML string. When the MS XML parser interprets this, all of the less-than and greater-than characters get escaped. The MS XML parser will escape the XML programmatically for you because it is treated as text/string. I could have used an AppendChild method to merge the XML, but then there would be no need for this article!

<request>
 <tkrnum>300005</tkrnum>
 <zertnum>20010003</zertnum>
 <username>DIRENZO</username>
 <result>implemented</result>
 <system_codes>Embedded Well-Formed XML is here - download 
               article source to see it</system_codes>
 </system_codes>
</request>

Here is the XSL code snippet that accesses the Parse function and describes the iteration process:

<xsl:variable name="syscodes" select="cs:parse(system_codes)"/>
<internal_sys_codes>
 <!-- Iterate here-->
 <xsl:for-each select="$syscodes//trresult" >     
  <sys_code>
   <icode><xsl:value-of select="srdcode"/></icode>
   <icomment><xsl:value-of select="comment"/></icomment>
  </sys_code>
 </xsl:for-each>
</internal_sys_codes>

Note the cs: prefix that references the namespace contained in the XSLT header. I put the result of cs:parse into syscodes. Then, the iteration of the new node-tree-fragment contained in syscodes occurs. Through this iteration, I can use the values contained in the originally embedded XML string (now a node-tree-fragment) and reshape the XML.

Points of Interest

The real crux of this technique is that it cannot be performed unless we do a server-side transform. The transform must be done with the .NET Framework, or an Invalid class string exception is thrown. Simply referencing the XSL file within the XML file will not work. See Image B for the results of the transformation.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mike DiRenzo
Web Developer
United States United States
Member
I have lived and worked throughout the globe (Brussels, London, Paris, West Indies, USA) as an IT consultant. My favorite S/W development concentrations are XML/XSLT, C#, Agile Model - Driven Development. I admire two well-renowned authors: Scott Ambler and Sal Mangano. Obviously there are many, many others but these two have been key to my successes over the years. I live and work in Charlotte, NC, USA and run a small S/W consulting practice called Business Automation Systems, Inc. I hold a Bachelors degree in Business with a concentration in Management Information Systems from the University of North Carolina at Charlotte.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralWow I never even thought about thismemberIsraelDC122 Mar '07 - 9:14 
Michael,
 
What a fantastic example. I was just looking of a simple format function example in JavaScript, but C#.... so much better.
 
Now I see so much more potential in my XSLT processing.

 
Israel Curiel
Generalvb .net - XSLT NamespacememberPatrick.Alex28 Nov '06 - 1:52 
Any Idea on what Could be the XSLT Namespace for vb .net?
 

 
Thanks
Patrick

GeneralRe: vb .net - XSLT NamespacememberMike DiRenzo21 Dec '06 - 15:40 
Alex,
From what I understand, javascript, c# are the only accepted scripting languages in transforms via the .Net framework. In classic ASP, vbscript is/was quite capable of being used.
I don't belive it is possible to use VB.NET inside a transfrom via the .Net Framework. But I could be wrong.
 

 
"In quiet and silence, the truth is made clear."

Questionxml transform to xml using xslt ???memberphucuong27321 May '06 - 3:07 
I have a xml file contents the list of questions.
For example :
<questions>
<question>
   <questioncontent>Question content 1</questioncontent>
   <answer>Answer 1</answer>
   <answer>Answer 2</answer>
   <answer>Answer 3</answer>
</question>
<question>
   <questioncontent>Question content 2</questioncontent>
   <answer>Answer 1</answer>
   <answer>Answer 2</answer>
</question>
<question>
   <questioncontent>Question content 3</questioncontent>
   <answer>Answer 1</answer>
   <answer>Answer 2</answer>
   <answer>Answer 3</answer>
   <answer>Answer 4</answer>
</question>
</questions>
how can i use xslt to transform the file above into another xml file with the order changed randomly( the order of question in the list & the answer in the question ).
The result, for example:
<questions>
<question>
   <questioncontent>Question content 2</questioncontent>
   <answer>Answer 1</answer>
   <answer>Answer 2</answer>
</question>
<question>
   <questioncontent>Question content 3</questioncontent>
   <answer>Answer 1</answer>
   <answer>Answer 3</answer>
   <answer>Answer 4</answer>
   <answer>Answer 2</answer>
</question>
<question>
   <questioncontent>Question content 1</questioncontent>
   <answer>Answer 2</answer>
   <answer>Answer 1</answer>
   <answer>Answer 3</answer>
</question>
</questions>
I hope you understand my question and answer me soon.
Thanks a lot.
AnswerRe: xml transform to xml using xslt ??? [modified]memberMike DiRenzo26 May '06 - 2:34 
You will need an index on each of your tags in the form of an attribute.
For example:
<question idx="0"/>
<question idx="1"/>
 
Then, either using c# or jscript, create a randomizer that will output some kind of index relative to the aforementioned and assigned indexes on each of your tags. The randomizer function will have to produce indexes in terms of a domain of indexes relative to the number elements you have.
 
Once you have a list of randomized indexes, you will need to have a template function that will receive a node list of nodes and output each node relative to the current index in the list - increment each index in your list and startover until all nodes have been outputed. This method will ensure the output of nodes is relative tothe randmoized list of indexes you produced.
 
Good luck.
 
-Mike

 
"In quiet and silence, the truth is made clear."
 
-- modified at 8:34 Friday 26th May, 2006

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 19 May 2006
Article Copyright 2006 by Mike DiRenzo
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid