2

I have to transform my xml output to html. I am following a tutorial at link text My code is outputting xml tags in a single line without any formatting with text value.I want the output as an HTML unordered list following hierarchical structure of parent child in xml file output.

Here is page output:

message msg 1message msg 1-1message msg 1-2message msg 1-2-1message msg 1-2-2message 
msg 1-2-2-1message msg 1-2-2-1-1message msg 1-2-2-1-2 

& here is page source:

<html:ul xmlns:html="http://www.w3.org/1999/xhtml"><html:li>message msg 1</html:li>
<html:ul><html:li>message msg 1-1</html:li><html:li>message msg 1-2</html:li><html:ul>
<html:li>message msg 1-2-1</html:li><html:li>message msg 1-2-2</html:li><html:ul>
<html:li>message msg 1-2-2-1</html:li><html:ul><html:li>message msg 1-2-2-1-1</html:li>
<html:li>message msg 1-2-2-1-2</html:li></html:ul></html:ul></html:ul></html:ul></html:ul>

Here is my code

php file:

<?php
# LOAD XML FILE
$XML = new DOMDocument();
$XML->load('messages.xml');

# START XSLT
$xslt = new XSLTProcessor();
$XSL = new DOMDocument();
$XSL->load('msg.xsl');
$xslt->importStylesheet( $XSL );
print $xslt->transformToXML( $XML );
?>

msg.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:html="http://www.w3.org/1999/xhtml">
  <xsl:output omit-xml-declaration="yes" />

  <xsl:template match="messages">
    <html:ul>
      <xsl:apply-templates select="message" />
    </html:ul>
  </xsl:template>

  <xsl:template match="message[message]">
    <html:li>message <xsl:value-of select="@msg_id" /></html:li>
    <html:ul>
      <xsl:apply-templates select="message" />
    </html:ul>
  </xsl:template>

  <xsl:template match="message">
    <html:li>message <xsl:value-of select="@msg_id" /></html:li>
    <xsl:apply-templates select="message" />
  </xsl:template>
</xsl:stylesheet>

messages.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="msg.xsl"?><messages>
    <message msg_id="1" emp_msg="msg 1" parent_msg_id="" parent_msg="" depth="0">
        <message msg_id="2" emp_msg="msg 1-1" parent_msg_id="1" parent_msg="msg 1" depth="1"/>
        <message msg_id="3" emp_msg="msg 1-2" parent_msg_id="1" parent_msg="msg 1" depth="1">
            <message msg_id="4" emp_msg="msg 1-2-1" parent_msg_id="3" parent_msg="msg 1-2" depth="2"/>
            <message msg_id="5" emp_msg="msg 1-2-2" parent_msg_id="3" parent_msg="msg 1-2" depth="2">
                <message msg_id="6" emp_msg="msg 1-2-2-1" parent_msg_id="5" parent_msg="msg 1-2-2" depth="3">
                    <message msg_id="7" emp_msg="msg 1-2-2-1-1" parent_msg_id="6" parent_msg="msg 1-2-2-1" depth="4"/>
                    <message msg_id="8" emp_msg="msg 1-2-2-1-2" parent_msg_id="6" parent_msg="msg 1-2-2-1" depth="4"/>
                </message>
            </message>
        </message>
    </message>
</messages>
9
  • Is the XML file not valid because of a cut & paste error or is that what you're trying to transform? - last line "</message" should be "</messages>" Commented Dec 2, 2010 at 13:36
  • What does your output look like, and how do you want it to look? Commented Dec 2, 2010 at 13:54
  • @Chris Bentley, that is cut & paste mistake only. I fixed the error, it was due to using 'loadXML' instead of 'load' to load xml doc. Though its not showing results, just outputting tags. I updated my question. Commented Dec 2, 2010 at 13:55
  • That's not the output I get here. Did you look at the page source? Commented Dec 2, 2010 at 14:12
  • @ Ignacio Vazquez-Abrams, it is displaying all xml tags with numbers added to it. Numbers probably it get from xml output as its a part of it. I added output to OP. Actually I want the output as an HTML unordered list following hierarchical structure of parent child in xml file output. & it should contain values of 'msg_id' & 'emp_msg'. Commented Dec 2, 2010 at 14:13

2 Answers 2

1

Your stylesheet does not output HTML but rather an XHTML fragment, and that in a way (with qualified names) that you need to serve it as application/xml to a browser (like Mozilla, Opera, Safari, IE 9, but not IE 6-8) that understands that content type.

So make sure you do something like

  header('Content-Type: application/xml');

before sending the content to the browser. Or drop any XHTML namespace and any prefixes from the result elements, then the XSLT stylesheet outputs an HTML fragment many more browsers can parse and understand as text/html and render it as you want.

Sign up to request clarification or add additional context in comments.

4 Comments

header is a PHP function php.net/manual/en/function.header.php so assuming you use PHP you need to make the sbown function call in your PHP code before sending any contents to the browser, so make sure you put it before the print statement.
@XCeptable: You can get rid of the html namespace by removing the xmlns:html attribute and removing the html: in front of each element. Make sure that you leave the xsl namespace alone, since it's required in order to make the XSLT work.
you are grate :), thanx a thousands times
@Ignacio Vazquez-Abrams, thanX a thousands times ignacio, your xsl is working very nice :) But still there is some work to do. As I used this xml by saving it locally, But in application, its generated dynamically by php code, so How do I do it there. Should I replace the 'loadXML' part with code that generates result set in xml, get that output in xml & use? OR should I put a new question for that?
0

To be crossbrowser, I would use this stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes"
                doctype-public="-//W3C//DTD HTML 4.0//EN"
                doctype-system="http://www.w3.org/TR/html4/strict.dtd"/>
    <xsl:template match="messages">
        <html>
            <body>
                <xsl:apply-templates select="*[1]"/>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="message[1]">
        <ul>
            <xsl:call-template name="makeListItem"/>
        </ul>
    </xsl:template>
    <xsl:template match="message" name="makeListItem">
        <li>
            <xsl:value-of select="concat('message ',@msg_id)" />
            <xsl:apply-templates select="*[1]"/>
        </li>
        <xsl:apply-templates select="following-sibling::*[1]"/>
    </xsl:template>
</xsl:stylesheet>

Output:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<body>
<ul>
 <li>message 1
  <ul>
   <li>message 2</li>
   <li>message 3
    <ul>
     <li>message 4</li>
     <li>message 5
      <ul>
       <li>message 6
        <ul>
         <li>message 7</li>
         <li>message 8</li>
        </ul>
       </li>
      </ul>
     </li>
    </ul>
   </li>
  </ul>
 </li>
</ul>
</body>
</html>

Render as:

  • message 1
    • message 2
    • message 3
      • message 4
      • message 5
        • message 6
          • message 7
          • message 8

Note: HTML DOCTYPE, no namespace. Also other approach to hierarchie processing with fine grained traversal.

5 Comments

@Alejandro, I used this but it prints simple xml without any formating
@XCeptable: Very strange! I've tested with your exact PHP code, your exact input sample and my stylesheet.
@XCeptable: That is because you are not ussing your exact PHP code as in question: you have added the Content Type header as suggested by @Martin Honnen, or you have added this Content Type in .htaccess file, or what ever post processor. That message is from browser and it means simple: "This is an XML document without CSS nor XSLT stylesheet, so I (browser) am going to use my own stylesheet"
@Alejandro, you are right, I have no words to thank as it all of a sudden make everything working as yours do not use any kind of headers. thanks a thousands again
@Alejandro, <xsl:value-of select="concat('',@msg_id,@emp_msg)" /> If I want to print one tag say msg_id only in root but not in child then how to do this ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.