Forum Moderators: open

Message Too Old, No Replies

Parsing my XML with XSL

         

Oxford

5:51 pm on May 29, 2007 (gmt 0)

10+ Year Member



I'm trying to use xsl to parse and format my xml, but am having a hard time finding an example xml/xsl file that looks like mine. I need to extract everything from "step" and it's corresponding id. Any help would be greatly appreciated. thanks you, ox.

Here is my sample xml code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myDocType (View Source for full doctype...)>
- <Presentation>
- <something>
<test system="mine" />
</something>
- <Find steps="9" type="great">
- <step id="1">
<param name="title">Hey Now</param>
<param name="actor">Michael</param>
</step>
- <step id="2">
<param name="title">Hey Now</param>
<param name="actor">Michael</param>
</step>
</Find>
</Presentation>

cmarshall

6:38 pm on May 29, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm a little unclear as to your exact requirements. The code seems very sparse.

One thing that I would highly recommend is to get yourself a copy of something like <oXygen/>. Think of it as an "IDE" for XML and XSLT development.

W3Schools [w3schools.com] has an X-cellent XSLT tutorial [w3schools.com]. Maybe that can help.

Oxford

9:04 pm on May 29, 2007 (gmt 0)

10+ Year Member



thanks for taking a look cmarshall. what i'm trying to do is format my xml data below. What I don't know, is how to write my xsl to extract in the example below, "step". It has an id="1" and then it has parameters. I want to write to the browser with xsl, the step number and then the param within that step. If it's still not clear, please let me know. ox

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myDocType (View Source for full doctype...)>
<Presentation>
<something>
<test system="mine" />
</something>
<Find steps="9" type="great">
<step id="1">
<param name="title">Hey Now</param>
<param name="actor">Michael</param>
</step>
<step id="2">
<param name="title">Hey Now</param>
<param name="actor">Michael</param>
</step>
</Find>
</Presentation>

cmarshall

10:12 pm on May 29, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So, is what you want to output [X]HTML?

Something like this?

<div id="Presentation">
<ul id="step_1">
<li class="title">Hey Now</li>
<li class="actor">Michael</li>
</ul>
<ul id="step_2">
<li class="title">Hey Now</li>
<li class="actor">Michael</li>
</ul>
</div>

Oxford

1:32 pm on May 30, 2007 (gmt 0)

10+ Year Member



XHTML , right, sorry for not mentioning that. That would be perfect. Using your example, I would also like to extract the "id" for that step. So...

<div id="Presentation">
<ul id="step_1">
<li class="title">1. Hey Now</li>
<li class="actor">Michael</li>
</ul>
<ul id="step_2">
<li class="title">2. Hey Now</li>
<li class="actor">Michael</li>
</ul>
</div>

Thank You!

cmarshall

1:41 pm on May 30, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Got it. Should be a breeze.

I'll get to it a bit later.

cmarshall

4:12 pm on May 30, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This will give you what you need. You should mess with the output element:

The XML:

<?xml version="1.0" encoding="UTF-8"?>
<Presentation>
<something>
<test system="mine" />
</something>
<Find steps="9" type="great">
<step id="1">
<param name="title">Hey Now</param>
<param name="actor">Michael</param>
</step>
<step id="2">
<param name="title">Hey Now</param>
<param name="actor">Michael</param>
</step>
</Find>
</Presentation>

The XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="no" method="html" version="4.01" doctype-system="http://www.w3c.org/tr/html4/strict.dtd" doctype-public="-//W3C//DTD HTML 4.01//EN"/>
<xsl:template match="/">
<html>
<head>
<title>test</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="/Presentation/Find[@type='great']">
<xsl:for-each select="step">
<xsl:element name="ul">
<xsl:attribute name="id">
<xsl:value-of select="concat('step_', @id)"/>
</xsl:attribute>
<xsl:element name="li">
<xsl:attribute name="class">title</xsl:attribute>
<xsl:value-of select="param[@name='title']"/>
</xsl:element>
<xsl:element name="li">
<xsl:attribute name="class">actor</xsl:attribute>
<xsl:value-of select="param[@name='actor']"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

[edited by: cmarshall at 4:24 pm (utc) on May 30, 2007]

Oxford

4:23 pm on May 30, 2007 (gmt 0)

10+ Year Member



that did it!

Oxford

7:24 pm on Jun 4, 2007 (gmt 0)

10+ Year Member



Now I'm on to error handling... I get back two different xml files, let me explain. If the information that I send to server is correct, I use the xsl above on the returned xml, it works great. But if an error is spotted, the structure of the xml file that I get back is different like the one below compared to the xml file I posted above.
So using the xsl template that you wrote, how would I incorporate the handling of two different xml data structures?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myDocType (View Source for full doctype...)>
<Presentation>
<FindError errorSent="This is the error">
</FindError>
</Presentation>

Thanks again,
Ox

cmarshall

7:41 pm on Jun 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Oh, that's fairly easy. You simply match a template to the error element, like so:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="no" method="html" version="4.01" doctype-system="http://www.w3c.org/tr/html4/strict.dtd" doctype-public="-//W3C//DTD HTML 4.01//EN"/>
<xsl:template match="/">
<html>
<head>
<title>test</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="/Presentation/Find[@type='great']">
<xsl:for-each select="step">
<xsl:element name="ul">
<xsl:attribute name="id">
<xsl:value-of select="concat('step_', @id)"/>
</xsl:attribute>
<xsl:element name="li">
<xsl:attribute name="class">title</xsl:attribute>
<xsl:value-of select="param[@name='title']"/>
</xsl:element>
<xsl:element name="li">
<xsl:attribute name="class">actor</xsl:attribute>
<xsl:value-of select="param[@name='actor']"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:template>

<xsl:template match="/Presentation/FindError">
<xsl:value-of select="@errorSent"/>
</xsl-template>

</xsl:stylesheet>

Oxford

7:54 pm on Jun 4, 2007 (gmt 0)

10+ Year Member



I tried that, now i'm getting this error:

The stylesheet does not contain a document element. The stylesheet may be empty, or it may not be a well-formed XML document

what could that be?

Oxford

7:57 pm on Jun 4, 2007 (gmt 0)

10+ Year Member



i did change a hyphen in the new code you posted with a : Now the page just comes back blank. Almost as if none of the criteria was met in the xsl so it wasn't processed, maybe?

Oxford

8:10 pm on Jun 4, 2007 (gmt 0)

10+ Year Member



never mind... I capitalized a letter and it shouldn't have been. Forgot the whole case sensitive stuff.

cmarshall

8:21 pm on Jun 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Whoops. I see the typo.

Yeah the capitalization thing gets me all the time.

I take it that it works now?

Oxford

8:30 pm on Jun 4, 2007 (gmt 0)

10+ Year Member



it does work but i keep trying to add more stuff to it. Now I'm trying to do an if statement.

if this error, write this
if this error, write that

<xsl:template match="/Presentation/FindError">
<xsl:if select="@errorSent='nowWay'"/>
write something here
</xsl:if>
<xsl:if select="@errorSent='youLittle'"/>
write something else here
</xsl:if>

</xsl-template>

Am i close?

[edited by: Oxford at 8:32 pm (utc) on June 4, 2007]

cmarshall

8:38 pm on Jun 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Close, but you don't use "select." You use "match."

XSLT is REAL dumb when it comes to conditional branches. If you want a choice between two or more paths, you need to use xsl:choose

Here are some relevant links:

[w3schools.com...]

[w3schools.com...]

These come from here: [w3schools.com...]

Oxford

8:52 pm on Jun 4, 2007 (gmt 0)

10+ Year Member



I tried replacing the select with match... is that all i needed to do, or is my code a little off still?

thanks

cmarshall

9:50 pm on Jun 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Post your code here, along with the XML you are parsing, and what you expect.

Again, I would HIGHLY recommend that you get <oXygen/> or XMLSpy. XSLT is a very difficult language to learn "blind."

With <oXygen/>, you can test each of these out, and figure it out in a few minutes.

cmarshall

11:55 pm on Jun 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Close, but you don't use "select." You use "match."

I made a mistake. It should be "test," not "match."

Oxford

1:02 am on Jun 5, 2007 (gmt 0)

10+ Year Member



I'll definately have to look into <oxygen/>

Here's the xml file

<?xml version="1.0" encoding="iso-8859-1"?>
<Presentation version="1.0">
<Find point="1" errorCode="" />
<Find point="2" errorCode="Not_FOUND" />
</Presentation>

-------------------------------------------

Then another xml could be received that has different errors

<?xml version="1.0" encoding="iso-8859-1"?>
<Presentation version="1.0">
<Find point="1" errorCode="Insufficient_INFO" />
<Find point="2" errorCode="" />
</Presentation>

[edited by: Oxford at 1:03 am (utc) on June 5, 2007]

cmarshall

1:38 am on Jun 5, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



<oXygen/> is cheap ($US48), and downloadable. You can be up and going with it in a few minutes. I think they even have a demo.

It's fairly complex, but not as complex as XMLSpy or Stylus Studio. It took me a couple of days to figure out. It's a Java app, so is fairly slow on my Mac (but it is cross-platform).

I don't know how I could have learned XSLT without it. All those examples I SMed you were done with it.

If you try correcting my goof (test instead of match), I'll bet your stuff starts working.

The nice thing about <oXygen/> is that it would have immediately told you about my goof. It would have immediately told me as well, so you know I didn't use it to test that.

Oxford

8:56 pm on Jun 5, 2007 (gmt 0)

10+ Year Member



cmarshall... you are the man! I figured out my problem using your solution. Thanks for taking a noob from no knowledge to basic understanding. Greatly appreciated!

Ox

[edited by: Oxford at 8:56 pm (utc) on June 5, 2007]