• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

XSLT StyleSheet Query (newbie)

 
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

I need some advice on how to retrieve the value of 2 attributes (@href, @title) in state.xml as part of transformation as follows:

[code] <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml">
- <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
………..
</head>
- <body>
<a shape="rect" name="top" />
+ <div id="container">
- <div id="content">
+ <div id="as1">
+ <div id="alphalinks">
<h1> Listing of all the states</h1>
+ <p>
- <table class="sresults">
- <tr>
- <td colspan="1" rowspan="1">
<a shape="rect" href="http://www.abc.com/areas/CA/fairy+land" title="Fairy Land, CA">Fairy Land</a>
</td>
- <td colspan="1" rowspan="1">
<a shape="rect" href="http://www.abc.com/areas/CA/wonder+land" title="Wonder Land, CA">Wonder Land</a>
</td>
……….
</tr>
</body>
</html>

Below is the content of stateStyleSheet.xsl:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<h2>Transformed State Detail</h2>
<table border="1">
<tr bgcolor="lightblue">
<th align="left">Area Link</th>
<th align="left">Area Name</th>
</tr>
<xsl:for-each select="/html/body/div[@id='content']/table[@class='sresults']/tr/td/a">
<tr>
<td><xsl:value-of select="@href"/></td>
<td><xsl:value-of select="@title"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>

</xsl:stylesheet>


Here is state.java together with XML Catalog to bring everything together:

SAXBuilder stateBuilder = new SAXBuilder("org.ccil.cowan.tagsoup.Parser", false);
FileInputStream stateIS = new FileInputStream("E:\\state.xml");
BufferedInputStream stateBIS = new BufferedInputStream(stateIS);
Document stateOriginaljdomDocument = stateBuilder.build(stateBIS);

TransformerFactory stateFactory = TransformerFactory.newInstance();
FileInputStream styleSheetIS = new FileInputStream("E:\\stateStyleSheet.xsl");
BufferedInputStream styleSheetBIS = new BufferedInputStream(styleSheetIS);
Transformer stateTransformer = stateFactory.newTransformer(new StreamSource(styleSheetBIS));
……

Output from transformation process gives:

<?xml version="1.0" encoding="UTF-8"?>
<html>
<body>
<h2>Transformed State Detail</h2>
<table border="1">
<tr bgcolor="lightblue">
<th align="left">Area Link</th>
<th align="left">Area Name</th>
</tr>
</table>
</body>
</html> [/code]I am not sure whether namespace has anything to do with it. The following XPath statement has worked on the same state.xml document:

XPath stateXPath = XPath.newInstance(
"/ns:html/ns:body/ns:div[@id='content']/ns:table[@class='sresults']/ns:tr/ns:td/ns:a");
stateXPath.addNamespace("ns", "http://www.w3.org/1999/xhtml");

I am using JDK1.6, Sax6.5.5, TagSoup 1.2, Resolver 1.2, JDOM1.1, Netbeans 6.1 on Windows XP platform.

Any assistance would be appreciated.

Thanks,

Jack

 
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That XPath expression should work in the XSLT program as well. Just declare the namespace in the root element of the XSLT.
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Paul,

How to declare the namespace in the root element of the XSLT?

I would appreciate a bit of guidance.

Many thanks,

Jack
 
Paul Clapham
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Just copy the namespace declaration from your XML document into your XSLT document. Put it right next to the namespace declaration that is already in the XSLT document.
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Paul,

Below is the content of stateStyleSheet.xsl after having added the default namespace as well as modified it slightly:


I am only interested in the @title (Fairy Land, Wonderland....) but it is giving a lot of rubbish. How to narrow the search further to narrow down the relevant data only?

Again, this "/html/body/div[@id='content']/table[@class='sresults']/tr/td/a" has worked in XPath.

Many thanks again,

Jack
 
Paul Clapham
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can't find elements in the default namespace using XPath. Use a namespace with a prefix. Since your example was using a namespace with a prefix, I thought you would do that.
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Paul,

You are correct and the XPath search should have included the namespace such as the following:


My problem is how to use the something equivalent to List & Iterator in XSLT stylesheet to pick up these values.

Your patience is very much appreciated.

Thanks,

Jack
 
Paul Clapham
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Does that mean you still don't know how to declare a namespace in the root element of your XSLT?

Look at the root element you have now:

Notice that it already includes a namespace declaration. But that's not the namespace you're interested in. So just add another namespace declaration, for the namespace that you are interested in:

That's the namespace whose URI is "http://www.w3.org/1999/xhtml". Now in your input document, notice that you have two declarations for that namespace URI. One of them has no prefix (so it's the default namespace for the document) and the other has the "html" prefix. But both are the same namespace, so in that document the element "html" could also be called "html:html" without changing anything.

So in your XSLT, if you want to refer to elements in the input document whose names don't have prefixes (such as a "div" element for example), those elements are in the default namespace, since one is declared. But a "div" element is the same as an "html:div" element because the namespace is declared twice. And if you put that second declaration into your XSLT document, then the transformer knows about that namespace and it can access an "html:div" element in an XPath expression.

Now, remember that namespace prefixes aren't significant. The namespace URI is what counts. So in your XSLT you could have this instead:

Now to access a "div" element in your input document, your XPath expression would refer to "ns:div". Of course you could use any prefix you liked here.
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Paul,

First of all, thank you very much for going through in detail on explaining how namespace work in XSLT. It is very much appreciated.


The error message produced is:

Exception in thread "main" org.jdom.IllegalNameException: The name "html:" is not legal for JDOM/XML Namespace prefixs: Namespace prefixes cannot contain colons.
at org.jdom.Namespace.getNamespace(Namespace.java:158)
at org.jdom.input.SAXHandler.startPrefixMapping(SAXHandler.java:498)
at org.xml.sax.helpers.XMLFilterImpl.startPrefixMapping(XMLFilterImpl.java:490)
at org.jdom.transform.JDOMResult$DocumentBuilder.startPrefixMapping(JDOMResult.java:529)
at com.icl.saxon.output.ContentHandlerProxy.startElement(ContentHandlerProxy.java:126)
at com.icl.saxon.output.ProxyEmitter.startElement(ProxyEmitter.java:80)
at com.icl.saxon.output.NamespaceEmitter.startElement(NamespaceEmitter.java:95)
.......

It doesn't look as though XSLT accept "xmlns:html:="http://www.w3.org/1999/xhtml" namespace.

Many thanks for your patience and assistance again,

Jack
 
Paul Clapham
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, that's right. You should use "html" as your prefix and not "html:". Look at your namespace declarations and see how they differ.
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Paul,

Thank you very much for all your advice on this query.

I now understood how namespace work in XSLT stylesheet.

Below is how stateStyleSheet.xsl which has worked beautifully:


Many thanks again,

Jack
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic