Solved

Pass Raw XML to XSLT Transformer

Posted on 2009-05-13
11
968 Views
Last Modified: 2013-11-18
Good morning!

I am trying to pass raw XML to a XslCompiledTransform object in C# (to Experts: the XSLT processor *may* not be relevant). I want to accept this raw XML for parsing within my XSLT file. I have been trying to use the document() function to get the nodes of the passed-in XML, but to no avail. I am attaching pseudo-ish code to hopefully better explain. Is what is shown in the code box possible? Or am I going to need to write out my "temporary" XML to disk in order to use document().

As a note, I am not bent on using document(); I merely want to be able to "for-each" through the "file" nodes of the passed in XML.
// Raw XML sample
<file>C:\some\path\and\file.txt</file><file>C:\another\path\and\file.dat</file>
 
 
// Looking to do something like
<xsl:param name="incomingXML" />
<xsl:variable name="xFormCopy" select="document($incomingXML/>
 
 
<xsl:for-each select="$xFormCopy/file">
// some work here...
</xsl:for-each>

Open in new window

0
Comment
Question by:käµfm³d   👽
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
11 Comments
 
LVL 39

Expert Comment

by:abel
ID: 24374262
Well, basically, you do not need to use document() at all. You mention that you use C#. That means that all you need to do is pass the XML file onto the parameters of the XslCompiledTransform object:

xslt.Transform("Xml/input.xml", xsltArgs, xmlOutputWriter);
0
 
LVL 39

Expert Comment

by:abel
ID: 24374281
Suppose if, for another reason, you want to send the filenames of the XML as parameters to the transformation, you can do that as follows, after which you can use document() the way you are saying you are using it in your example XSLT.

XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddParam("incomingXMLName", "", "pathToXml.XML");
xslt.Transform("someDefault.xml", xsltArgs, xmlOutputWriter);

Open in new window

0
 
LVL 75

Author Comment

by:käµfm³d 👽
ID: 24374379
abel,

I do not need to process the files listed in "<file></file>" tags. I am going to list them in my output. So for something like

    <file>C:\some\path\and\file.txt</file><file>C:\another\path\and\file.dat</file>

Disregarding the other formatting that will take place (various HTML formatting), my output will be

    C:\some\path\and\file.txt
    C:\another\path\and\file.dat

I have a main XSLT document and within that document, I want to be able to accept a parameter that is the raw XML listed above and (unless there is a better way) do a "for-each" like operation on each "file" to display it in the output.

I am basically listing the files in a d irectory and I do not know how many files will be in the directory. Let me know if I can clarify further :)
0
Setting up LaraDock for Laravel

Learn how to set up LaraDock in a Laravel project - LaraDock gives us an easy way to run a Laravel application using Docker in a single command.

 
LVL 39

Expert Comment

by:abel
ID: 24374446
> unless there is a better way

my first comment was about that better way. The input document needs to be specified anyway, why would you want to specify it through a parameter? Unless you have a different input document that you are already processing and you want this one next to it, which was my second comment: using a parameter.

The XSLT is pretty much OK already, use the following, where I slightly amended your code, with my code of my second comment:

<xsl:param name="incomingXMLName" />
 
<xsl:template match="/">
   <xsl:apply-templates select="document($incomingXMLName)/file" />
</xsl:template>
 
<xsl:template match="file">
    <xsl:value-of select="text()" />
    <xsl:text>&#xA;</xsl;text>
</xsl:template>

Open in new window

0
 
LVL 75

Author Comment

by:käµfm³d 👽
ID: 24374717
Ok, forgive me if I'm just not understanding, but here is the code I am dealing with.
//////////////////////////////////////////////////////
// C# side
//////////////////////////////////////////////////////
 
private string getIrsFileName(string sSubPath) {
    List<string> xmlFileList = new List<string>();
    StringBuilder files = new StringBuilder("<?xml version=\"1.0\" ?>");
    sSubPath = sSubPath + @"\irs\xml\";
    string[] dirFiles = Directory.GetFiles(sSubPath, "*.xml", SearchOption.TopDirectoryOnly);
    
    foreach (string file in dirFiles)
    {
        files.AppendFormat("<ts:file>{0}</ts:file>\n", file);
    }
 
    return files.ToString();  // Returns an XML string like "<ts:file>C:\some\file.txt</ts:file><ts:file>C:\some\morefiles.txt</ts:text>"
}
 
//////////////////////////////////////////////////////
// XSLT code
//////////////////////////////////////////////////////
 
xsltParams.AddParam("irsdataxmlPath", string.Empty, getIrsFileName("C:\some\parent\dir"));
 
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////
// In XSLT document
//////////////////////////////////////////////////////
<xsl:param name="irsdataxmlPath" />  <!-- Contains textual data of the form "<ts:file>C:\some\file.txt</ts:file><ts:file>C:\some\morefiles.txt</ts:text>"
 
<!-- I want to treat the above as a node set rather than just a variable containing text -->

Open in new window

0
 
LVL 75

Author Comment

by:käµfm³d 👽
ID: 24374736
As far as I've tested, document() won't work on the xsl:param "irsdataxmlPath" because it is not a valid file path; rather it is XML data.
0
 
LVL 39

Expert Comment

by:abel
ID: 24375420
> because it is not a valid file path; rather it is XML data.

exactly. Which is why I tried to explain somehow that you should not use this semantics. But I thought that the XML document was on the disk, which is why I explained the way I did.

Using the method above, you won't succeed without resorting to extension methods. However, what you can do, is create the document, that you now create by hand, by the XML DOM classes (which is always much preferred over doing it by hand, to prevent coding mistakes). The, the resulting document can be given as an argument, without having to resort to placing it on disk first.

I can try to workout an example if you want that...
0
 
LVL 39

Accepted Solution

by:
abel earned 500 total points
ID: 24376008
Apparently, that approach works, and better than I expected. Here you go:

// Create the document, change this such that you load your file list here
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", "no"));
 
// create root node <files>
XmlElement files = doc.CreateElement("files");
 
// <file>...</file>
XmlElement file = doc.CreateElement("file");
file.AppendChild(doc.CreateTextNode("c:/temp/text1.txt"));
files.AppendChild(file);
 
// other way for <file>...</file>
file = (XmlElement) file.Clone();
file.InnerText = "c:/temp/text2.txt";
files.AppendChild(file);
 
// create xml document by adding the root node <files>
doc.AppendChild(files);
 
// create arguments and add params
XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddParam("externalDocument", "", doc);
xslt.Transform("someDefault.xml", xsltArgs, xmlOutputWriter);

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24376038
I kept the XSLT document extraordinarily simple, it is just a proof of concept. Below is the XSLT and the output XML from the above code:



<!-- xslt -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
    <xsl:param name="externalDocument" />
 
    <xsl:template match="/">
        <xsl:copy>
            <xsl:copy-of select="$externalDocument/*" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheeet>
 
<!-- output xml -->
<?xml version="1.0" encoding="utf-8"?>
<files>
  <file>c:/temp/text1.txt</file>
  <file>c:/temp/text2.txt</file>
</files>

Open in new window

0
 
LVL 75

Author Closing Comment

by:käµfm³d 👽
ID: 31580942
Thanks abel. I was not aware that you could pass an XMLDocument object to the XSLT processor in C#--although I guess in hindsight it makes sense! Sorry for the delay in closing the question, and thanks again for your help.
0
 
LVL 39

Expert Comment

by:abel
ID: 24398635
You're welcome! :)
0

Featured Post

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I found this questions asking how to do this in many different forums, so I will describe here how to implement a solution using PHP and AJAX. The logical flow for the problem should be: Write an event handler for the first drop down box to get …
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
The viewer will the learn the benefit of plain text editors and code an HTML5 based template for use in further tutorials.
Suggested Courses

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question