?
Solved

XSLT Transformation

Posted on 2008-11-19
8
Medium Priority
?
939 Views
Last Modified: 2013-12-17
Hello,

I'am trying to do an XSLT transformation from XML to HTML, but when I look at the HTML afterwards it just shows the XML code in the view source.  I have a string[] with multiple paths and this is how I'am transforming them:

   foreach (string webPath in webPaths)
                {
                    WebClient write = new WebClient();
                    Stream str = write.OpenRead(webPath);
                    TextReader tw = new StreamReader(str);
                    processServer(tw);

                    xslTrans.Load("stats_transform.xslt");
                    xslTrans.Transform(webPath, globalWriter);

                     tw.Close();
                }

And here are my globals:
public static XslCompiledTransform xslTrans = new XslCompiledTransform();
public static XmlTextWriter globalWriter = new XmlTextWriter("stats.html", null);

When I look at the HTML, I expected it to be formatted by my XSLT rules, but all I get is the data between the tags, and not even the tag names are being displayed.

This is a sample of my XML:
  <?xml version="1.0" encoding="us-ascii" standalone="yes" ?>
- <Host xmlns="myServer">
- <Drive xmlns="C:\">
  <Capacity>31.21</Capacity>
  <AmtUsed>23.06</AmtUsed>
  <AmtNotUsed>8.16</AmtNotUsed>
  <PercentFree>26</PercentFree>
  </Drive>
</Host>

My XSLT is like this (not fully functional - just for testing so far):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="html" />

    <xsl:template match="/">
            <table border="1" cellspacing="1" align="center">
                  <xsl:for-each select="Host/Drive">
                        <tr>
                              <td>
                              Capacity: <xsl:value-of select="Capacity"/>
                              </td>
                        </tr>
                        
                  </xsl:for-each>
                  
            </table>
      </xsl:template>
</xsl:stylesheet>

Anyone have any ideas?
0
Comment
Question by:igor92128
  • 4
  • 4
8 Comments
 
LVL 19

Expert Comment

by:zc2
ID: 22995955
your xml has two namespaces declarations:
xmlns="myServer" and  xmlns="C:\"
you need explicitly declate them in the xsl :
xmlns:m="myServer" xmlns:c="C:\"         (the names instead of "m" and "c"  may be any)
and them use the same names as the tag prefixes:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:m="myServer" xmlns:c="C:\">
    <xsl:output method="html" />
 
    <xsl:template match="/">
            <table border="1" cellspacing="1" align="center">
                  <xsl:for-each select="m:Host/c:Drive">
                        <tr>
                              <td>
                              Capacity: <xsl:value-of select="c:Capacity"/>
                              </td>
                        </tr>
                        
                  </xsl:for-each>
                  
            </table>
      </xsl:template>
</xsl:stylesheet>

Open in new window

0
 

Author Comment

by:igor92128
ID: 22996275
I just tried this and my HTML file is still just a bunch of numbers without tags or anything. So if I have xmlns in my XML file and they are different for each file, I'd need to build a pretty long XSLT file? I can't use for-each?

Maybe I'am not building my XML file correctly?

Iam declaring an xmlTextWriter: public static XmlTextWriter xwriter;

and using it like this:

xwriter = new XmlTextWriter(file, System.Text.Encoding.ASCII);
xwriter.WriteStartDocument(true);
xwriter.Formatting = Formatting.Indented;

xwriter.WriteStartElement("Host", gethostname());

foreach(DriveInfo d in alldrives)
{
xwriter.WriteStartElement("Drive", d.Name)
xwriter.WriteElementString("Capacity", d.Name, mycalculations);
...
...
xwriter.WriteEndElement();
}

            xwriter.WriteEndElement();
            xwriter.WriteEndDocument();
            xwriter.Close();
0
 
LVL 19

Expert Comment

by:zc2
ID: 22996542
Did you intend to create the "Host" and "Drive" elements that way - with their value as a namespace?
It looks very odd...
(The second parameter  of WriteStartElement() creates a namespace declaration.)
Those values would be better stored in an named attribute using the WriteAttributeString() method.
Like:

xwriter.WriteStartElement("Host");
xwriter.WriteAttributeString("name", gethostname());
foreach(DriveInfo d in alldrives)
{
xwriter.WriteStartElement("Drive")
xwriter.WriteAttributeString("name", d.Name);
xwriter.WriteElementString("Capacity", d.Name, mycalculations);
...
...
xwriter.WriteEndElement();
}

Open in new window

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Author Comment

by:igor92128
ID: 22996689
This is my XML file now, but I would need to get rid of the xmlns statements right?

<?xml version="1.0" encoding="us-ascii" standalone="yes" ?>
- <Host Name="myhost">
- <Drive Name="C:\">
  <Capacity xmlns="C:\">74.45</Capacity>
  <AmtUsed xmlns="C:\">61.12</AmtUsed>
  <AmtNotUsed xmlns="C:\">13.33</AmtNotUsed>
  <PercentFree xmlns="C:\">18</PercentFree>
  </Drive>
  </Host>
0
 

Author Comment

by:igor92128
ID: 22996766
Ok, I got the XML correct now I think:

<Host Name="myhost">
- <Drive Name="C:\">
  <Size>74.45</Size>
  <AmtUsed>61.12</AmtUsed>
  <AmtNotUsed>13.33</AmtNotUsed>
  <PercentFree>18</PercentFree>
  </Drive>
  </Host>

Will try to do the XSLT transform with this.
0
 
LVL 19

Expert Comment

by:zc2
ID: 22996909
your last xml does not contain the Capacity element...
0
 

Author Comment

by:igor92128
ID: 22997158
I just renamed Capacity. Ok, I got it working but I have 1 more problem:

How do I select the value inside the tags for Host and Drive? Those values are blank in the result HTML file. All other values show up fine. Sample XSLT code is below.
<body>
				<p>
					Host: <xsl:for-each select="/Host"><br/>
						Drive: <xsl:for-each select="/Host/Drive"><br/>
							Capacity: <xsl:value-of select="Size"/><br/>
							Amount Used: <xsl:value-of select="AmtUsed"/><br/>

Open in new window

0
 
LVL 19

Accepted Solution

by:
zc2 earned 2000 total points
ID: 22997255
add a "@" before the attribute name to address its value, like:
Drive: <xsl:value-of select="@Name"/><br/>

The latest xslt is not quite correct.
You have two for-each loops: one for hosts and one for drives in each host.

But in your solution the inner loop will enumerate _all_ drives from all hosts.
The following enumerqates drives only in the current host:
<body>
  <p>
    <xsl:for-each select="Host">
      Host: <xsl:value-of select="@Name"/><br/>
       <xsl:for-each select="Drive">
         Drive: <xsl:value-of select="@Name"/><br/>
         Capacity: <xsl:value-of select="Size"/><br/>
         Amount Used: <xsl:value-of select="AmtUsed"/><br/>
       </xsl:for-each>
    </xsl:for-each>
  </p>
</body>

Open in new window

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
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 …
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…
The viewer will the learn the benefit of plain text editors and code an HTML5 based template for use in further tutorials.
Suggested Courses

840 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