tmricha
asked on
Using JSP to read streaming XML, w/o tag libs
I am new to the JSP development world and have recently been asked to take on a project which I am not too familiar with.
What I need to do is this:
Grab/Call an xml stream via url (i.e. http://www.domain.com/xml/opentickets.xml)
This returns a valid XML document of the structure: (real example of output)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HDTickets [
<!ELEMENT Ticket (ticketID, title,status, owner, creationTime)>
<!ELEMENT ticketID (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT status (#PCDATA)>
<!ELEMENT owner (#PCDATA)>
<!ELEMENT creationTime (#PCDATA)>
]>
<HDTickets>
<Ticket ticketID="030625_1317672"
title ="EAP Not Working From outside."
status ="Pending - User Delay"
owner ="e_operations"
creationTime ="2003-06-25 10:29:31">
</Ticket>
<Ticket ticketID="040414_1339696"
title ="Shared Mailbox Creation"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 08:26:58">
</Ticket>
<Ticket ticketID="040414_1339697"
title ="Other(Act)"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 16:28:16">
</Ticket>
</HDTickets>
Using JSP, I would like to be able to read the values of each ticket(ticketid, title, status, owner, creationtime), assigne them to a variable, and then display them on the page as pure text
( out.println="Ticket ID= " & varTicketID )
I have no control over the format of the XML coming back, nor do I have ownership over the server to install any special software.
I figure there has to be a way that JSP can read this, asign data to variables, and then display....
The problem is, I really have no idea where to begin, and most sites I have been able to find discuss using specific parsers, installs, etc.
PLEASE HELP ME :)
What I need to do is this:
Grab/Call an xml stream via url (i.e. http://www.domain.com/xml/opentickets.xml)
This returns a valid XML document of the structure: (real example of output)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HDTickets [
<!ELEMENT Ticket (ticketID, title,status, owner, creationTime)>
<!ELEMENT ticketID (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT status (#PCDATA)>
<!ELEMENT owner (#PCDATA)>
<!ELEMENT creationTime (#PCDATA)>
]>
<HDTickets>
<Ticket ticketID="030625_1317672"
title ="EAP Not Working From outside."
status ="Pending - User Delay"
owner ="e_operations"
creationTime ="2003-06-25 10:29:31">
</Ticket>
<Ticket ticketID="040414_1339696"
title ="Shared Mailbox Creation"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 08:26:58">
</Ticket>
<Ticket ticketID="040414_1339697"
title ="Other(Act)"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 16:28:16">
</Ticket>
</HDTickets>
Using JSP, I would like to be able to read the values of each ticket(ticketid, title, status, owner, creationtime), assigne them to a variable, and then display them on the page as pure text
( out.println="Ticket ID= " & varTicketID )
I have no control over the format of the XML coming back, nor do I have ownership over the server to install any special software.
I figure there has to be a way that JSP can read this, asign data to variables, and then display....
The problem is, I really have no idea where to begin, and most sites I have been able to find discuss using specific parsers, installs, etc.
PLEASE HELP ME :)
Right -- Shortly I'll paste in a good DTD for the attributes version, and also some sample code for when it's elements (your code is close, but not quite).
This is a job for XSL. You can write an XSL stylesheet to transform the XML into HTML, or just text. The XSL stylesheet's essential elements would be something like this:
<xsl:stylesheet ...>
<xsl:output method="text" omit-xml-declaration="true "/>
<xsl:template match="Ticket">TicketID=<x sl:value-o f select="@ticketID"/></xsl: template>
</xsl:stylesheet>
You may need to tweak that a little but that's basically it. You could also switch this to generate HTML if desired. Here is a good place to learn about XSL: http://www.w3schools.com/xsl/
If you are able to use the JSTL tags in your JSP application, then it can make this task easy. You would be able to generate the text you want in your JSP with a tag like this:
<c:import url="http://www.domain.com/xml/opentickets.xml" var="theXML"/>
<x:transform xslt="*the text of your stylesheet*" doc="${theXML}"/>
I haven't tested it but I think that's basically right.
You can find out more about JSTL here: java.sun.com/products/jsp/ jstl/
This is a good JSTL reference sheet: http://www.jadecove.com/jstl-quick-reference.pdf
If this approach is viable then I think it is the cleanest way to go. No coding needed.
<xsl:stylesheet ...>
<xsl:output method="text" omit-xml-declaration="true
<xsl:template match="Ticket">TicketID=<x
</xsl:stylesheet>
You may need to tweak that a little but that's basically it. You could also switch this to generate HTML if desired. Here is a good place to learn about XSL: http://www.w3schools.com/xsl/
If you are able to use the JSTL tags in your JSP application, then it can make this task easy. You would be able to generate the text you want in your JSP with a tag like this:
<c:import url="http://www.domain.com/xml/opentickets.xml" var="theXML"/>
<x:transform xslt="*the text of your stylesheet*" doc="${theXML}"/>
I haven't tested it but I think that's basically right.
You can find out more about JSTL here: java.sun.com/products/jsp/
This is a good JSTL reference sheet: http://www.jadecove.com/jstl-quick-reference.pdf
If this approach is viable then I think it is the cleanest way to go. No coding needed.
OK. First off, here's a DTD embedded in the XML that actually matches the data you're getting. Your offshore guys are just way off. Then I've pasted in some code that is exactly like what I gave you before, except that it requests a "validating parser." This should work fine on your server as well -- try it. I've put a comment with a lot of stars next to the line that is changed for validation.
Now, if you validate, you normally would create a special error handling that would, say, dump error information to the server console. For that, you're getting into real Java code for dealing with XML -- at that point, you should start reading up on Java, XML, JSP, more generally.
Next I'll post something that would work if they changed the feed to use elements instead of attributes.
seanrowan's post above is very similar to my original JSTL suggestion. But since you can't easily deploy the JSTL jars, a pure JSP solution is probably good for now.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HDTickets [
<!ELEMENT HDTickets (Ticket)*>
<!ELEMENT Ticket (#PCDATA)>
<!ATTLIST Ticket
ticketID CDATA #REQUIRED
title CDATA #REQUIRED
status CDATA #REQUIRED
owner CDATA #REQUIRED
creationTime CDATA #REQUIRED>
]>
<HDTickets>
<Ticket ticketID="030625_1317672"
title ="EAP Not Working From outside."
status ="Pending - User Delay"
owner ="e_operations"
creationTime ="2003-06-25 10:29:31"/>
<Ticket ticketID="040414_1339696"
title ="Shared Mailbox Creation"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 08:26:58">
</Ticket>
<Ticket ticketID="040414_1339697"
title ="Other(Act)"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 16:28:16">
</Ticket>
</HDTickets>
I've posted this at http://7fff.com/tickets3.xml
Here's the JSP:
<%@ page import="java.io.IOExceptio n" %>
<%@ page import="java.util.ArrayLis t" %>
<%@ page import="javax.xml.parsers. DocumentBu ilder" %>
<%@ page import="javax.xml.parsers. DocumentBu ilderFacto ry" %>
<%@ page import="javax.xml.parsers. ParserConf igurationE xception" %>
<%@ page import="org.w3c.dom.Docume nt" %>
<%@ page import="org.w3c.dom.Elemen t" %>
<%@ page import="org.w3c.dom.NodeLi st" %>
<%@ page import="org.xml.sax.SAXExc eption" %>
<%
ArrayList exceptionList = new ArrayList();
ArrayList ticketIDs = new ArrayList();
DocumentBuilder parser = null;
Document d = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.new Instance() ;
dbf.setValidating(true); // ***** Now parser validates according to embedded DTD *****
try {
parser = dbf.newDocumentBuilder();
d = parser.parse("http://7fff.com/tickets3.xml");
} catch (ParserConfigurationExcept ion e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (d != null) {
NodeList tickets = d.getElementsByTagName("Ti cket");
for (int i = 0; i < tickets.getLength(); i++) {
Element e = (Element) tickets.item(i);
ticketIDs.add(e.getAttribu te("ticket ID").toStr ing());
}
}
%>
<html>
<body>
<%
if (exceptionList.size() != 0) {
out.println("The following exceptions were encountered: <br>");
for (int i = 0; i < exceptionList.size(); i++)
out.println("<li> " + exceptionList.get(i));
}
out.println("Number of Tickets found: " + ticketIDs.size());
out.println("<p>");
out.print("Ticket IDs: <br>");
for (int i = 0; i < ticketIDs.size(); i++)
out.println("<li> " + ticketIDs.get(i));
%>
</body>
</html>
Now, if you validate, you normally would create a special error handling that would, say, dump error information to the server console. For that, you're getting into real Java code for dealing with XML -- at that point, you should start reading up on Java, XML, JSP, more generally.
Next I'll post something that would work if they changed the feed to use elements instead of attributes.
seanrowan's post above is very similar to my original JSTL suggestion. But since you can't easily deploy the JSTL jars, a pure JSP solution is probably good for now.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HDTickets [
<!ELEMENT HDTickets (Ticket)*>
<!ELEMENT Ticket (#PCDATA)>
<!ATTLIST Ticket
ticketID CDATA #REQUIRED
title CDATA #REQUIRED
status CDATA #REQUIRED
owner CDATA #REQUIRED
creationTime CDATA #REQUIRED>
]>
<HDTickets>
<Ticket ticketID="030625_1317672"
title ="EAP Not Working From outside."
status ="Pending - User Delay"
owner ="e_operations"
creationTime ="2003-06-25 10:29:31"/>
<Ticket ticketID="040414_1339696"
title ="Shared Mailbox Creation"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 08:26:58">
</Ticket>
<Ticket ticketID="040414_1339697"
title ="Other(Act)"
status ="Solving"
owner ="clarify"
creationTime ="2004-04-14 16:28:16">
</Ticket>
</HDTickets>
I've posted this at http://7fff.com/tickets3.xml
Here's the JSP:
<%@ page import="java.io.IOExceptio
<%@ page import="java.util.ArrayLis
<%@ page import="javax.xml.parsers.
<%@ page import="javax.xml.parsers.
<%@ page import="javax.xml.parsers.
<%@ page import="org.w3c.dom.Docume
<%@ page import="org.w3c.dom.Elemen
<%@ page import="org.w3c.dom.NodeLi
<%@ page import="org.xml.sax.SAXExc
<%
ArrayList exceptionList = new ArrayList();
ArrayList ticketIDs = new ArrayList();
DocumentBuilder parser = null;
Document d = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.new
dbf.setValidating(true); // ***** Now parser validates according to embedded DTD *****
try {
parser = dbf.newDocumentBuilder();
d = parser.parse("http://7fff.com/tickets3.xml");
} catch (ParserConfigurationExcept
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (d != null) {
NodeList tickets = d.getElementsByTagName("Ti
for (int i = 0; i < tickets.getLength(); i++) {
Element e = (Element) tickets.item(i);
ticketIDs.add(e.getAttribu
}
}
%>
<html>
<body>
<%
if (exceptionList.size() != 0) {
out.println("The following exceptions were encountered: <br>");
for (int i = 0; i < exceptionList.size(); i++)
out.println("<li> " + exceptionList.get(i));
}
out.println("Number of Tickets found: " + ticketIDs.size());
out.println("<p>");
out.print("Ticket IDs: <br>");
for (int i = 0; i < ticketIDs.size(); i++)
out.println("<li> " + ticketIDs.get(i));
%>
</body>
</html>
Alright, here's the "elements" version of the XML with the embedded DTD (see http://7fff.com/tickets2.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HDTickets [
<!ELEMENT HDTickets (Ticket)*>
<!ELEMENT Ticket (ticketID, title,status, owner, creationTime)>
<!ELEMENT ticketID (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT status (#PCDATA)>
<!ELEMENT owner (#PCDATA)>
<!ELEMENT creationTime (#PCDATA)>
]>
<HDTickets>
<Ticket>
<ticketID>030625_1317672</ ticketID>
<title>EAP Not Working From outside.</title>
<status>Pending - User Delay</status>
<owner>e_operations</owner >
<creationTime>2003-06-25 10:29:31</creationTime>
</Ticket>
<Ticket>
<ticketID>040414_1339697</ ticketID>
<title>Other(Act)</title>
<status>Solving</status>
<owner>clarify</owner>
<creationTime>2004-04-14 16:28:16</creationTime>
</Ticket>
</HDTickets>
And here's the code. To understand how the DOM is being traversed, you'll need to read up on it. As you move along with your Java/JSP knowledge, you would want to take a lot of this parsing code and put it in a real Java class. Then have the JSP call that class. Or, as I said in the earlier post, if you can upgrade your server to use JSP 1.2, you could use JSTL and have virtually no Java code -- which would be much easier to maintain.
<%@ page import="java.io.IOExceptio n" %>
<%@ page import="java.util.ArrayLis t" %>
<%@ page import="javax.xml.parsers. DocumentBu ilder" %>
<%@ page import="javax.xml.parsers. DocumentBu ilderFacto ry" %>
<%@ page import="javax.xml.parsers. ParserConf igurationE xception" %>
<%@ page import="org.w3c.dom.Docume nt" %>
<%@ page import="org.w3c.dom.Elemen t" %>
<%@ page import="org.w3c.dom.NodeLi st" %>
<%@ page import="org.w3c.dom.Node" %>
<%@ page import="org.xml.sax.SAXExc eption" %>
<%
ArrayList exceptionList = new ArrayList();
ArrayList ticketIDs = new ArrayList();
ArrayList titles = new ArrayList();
DocumentBuilder parser = null;
Document d = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.new Instance() ;
dbf.setValidating(true); // ***** Now parser validates according to embedded DTD *****
dbf.setIgnoringElementCont entWhitesp ace(true); // ***** Very important to simplify parsing *****
try {
parser = dbf.newDocumentBuilder();
d = parser.parse("http://7fff.com/tickets2.xml");
} catch (ParserConfigurationExcept ion e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (d != null) {
NodeList tickets = d.getElementsByTagName("Ti cket");
for (int i = 0; i < tickets.getLength(); i++) {
Node ticketNode = tickets.item(i);
NodeList ticketElements = ticketNode.getChildNodes() ;
NodeList children;
String val;
// Deal with the ticketID
Node ticketIDNode = ticketElements.item(0);
children = ticketIDNode.getChildNodes ();
val = "";
if (children.getLength() != 0)
val = children.item(0).getNodeVa lue();
ticketIDs.add(val);
// Deal with the title
Node titleIDNode = ticketElements.item(1);
children = titleIDNode.getChildNodes( );
val = "";
if (children.getLength() != 0)
val = children.item(0).getNodeVa lue();
titles.add(val);
}
}
%>
<html>
<body>
<%
if (exceptionList.size() != 0) {
out.println("The following exceptions were encountered: <br>");
for (int i = 0; i < exceptionList.size(); i++)
out.println("<li> " + exceptionList.get(i));
}
out.println("Number of Tickets found: " + ticketIDs.size());
out.println("<p>");
out.print("Ticket ID: title <br>");
for (int i = 0; i < ticketIDs.size(); i++)
out.println("<li> " + ticketIDs.get(i) + ": '" + titles.get(i) + "'");
%>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HDTickets [
<!ELEMENT HDTickets (Ticket)*>
<!ELEMENT Ticket (ticketID, title,status, owner, creationTime)>
<!ELEMENT ticketID (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT status (#PCDATA)>
<!ELEMENT owner (#PCDATA)>
<!ELEMENT creationTime (#PCDATA)>
]>
<HDTickets>
<Ticket>
<ticketID>030625_1317672</
<title>EAP Not Working From outside.</title>
<status>Pending - User Delay</status>
<owner>e_operations</owner
<creationTime>2003-06-25 10:29:31</creationTime>
</Ticket>
<Ticket>
<ticketID>040414_1339697</
<title>Other(Act)</title>
<status>Solving</status>
<owner>clarify</owner>
<creationTime>2004-04-14 16:28:16</creationTime>
</Ticket>
</HDTickets>
And here's the code. To understand how the DOM is being traversed, you'll need to read up on it. As you move along with your Java/JSP knowledge, you would want to take a lot of this parsing code and put it in a real Java class. Then have the JSP call that class. Or, as I said in the earlier post, if you can upgrade your server to use JSP 1.2, you could use JSTL and have virtually no Java code -- which would be much easier to maintain.
<%@ page import="java.io.IOExceptio
<%@ page import="java.util.ArrayLis
<%@ page import="javax.xml.parsers.
<%@ page import="javax.xml.parsers.
<%@ page import="javax.xml.parsers.
<%@ page import="org.w3c.dom.Docume
<%@ page import="org.w3c.dom.Elemen
<%@ page import="org.w3c.dom.NodeLi
<%@ page import="org.w3c.dom.Node" %>
<%@ page import="org.xml.sax.SAXExc
<%
ArrayList exceptionList = new ArrayList();
ArrayList ticketIDs = new ArrayList();
ArrayList titles = new ArrayList();
DocumentBuilder parser = null;
Document d = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.new
dbf.setValidating(true); // ***** Now parser validates according to embedded DTD *****
dbf.setIgnoringElementCont
try {
parser = dbf.newDocumentBuilder();
d = parser.parse("http://7fff.com/tickets2.xml");
} catch (ParserConfigurationExcept
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (d != null) {
NodeList tickets = d.getElementsByTagName("Ti
for (int i = 0; i < tickets.getLength(); i++) {
Node ticketNode = tickets.item(i);
NodeList ticketElements = ticketNode.getChildNodes()
NodeList children;
String val;
// Deal with the ticketID
Node ticketIDNode = ticketElements.item(0);
children = ticketIDNode.getChildNodes
val = "";
if (children.getLength() != 0)
val = children.item(0).getNodeVa
ticketIDs.add(val);
// Deal with the title
Node titleIDNode = ticketElements.item(1);
children = titleIDNode.getChildNodes(
val = "";
if (children.getLength() != 0)
val = children.item(0).getNodeVa
titles.add(val);
}
}
%>
<html>
<body>
<%
if (exceptionList.size() != 0) {
out.println("The following exceptions were encountered: <br>");
for (int i = 0; i < exceptionList.size(); i++)
out.println("<li> " + exceptionList.get(i));
}
out.println("Number of Tickets found: " + ticketIDs.size());
out.println("<p>");
out.print("Ticket ID: title <br>");
for (int i = 0; i < ticketIDs.size(); i++)
out.println("<li> " + ticketIDs.get(i) + ": '" + titles.get(i) + "'");
%>
</body>
</html>
ASKER
One final request. I have a string that returns date and time (example: "2004-04-14 16:29:41").
I just want the date portion. How do I split this up.
I know in VB I search for the position of the [space], and then trim the string to that length. But I dont know the search-for position command in jsp.
Thanks again!
I just want the date portion. How do I split this up.
I know in VB I search for the position of the [space], and then trim the string to that length. But I dont know the search-for position command in jsp.
Thanks again!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Here's another way to do it that will work on JDKs prior to 1.4, if that helps too. It may be marginally faster.
String yourString = "2004-04-14 16:29:41";
String datePortion = yourString.substring(0, yourString.indexOf(' '));
String yourString = "2004-04-14 16:29:41";
String datePortion = yourString.substring(0, yourString.indexOf(' '));