Unable to Parse Parent / Child Elements using SAX XML Parser (Android) - java

I'm attempting to following this example of SAX XML Parser: How to parse XML using the SAX parser
However when debugging - some items are returning null. I have verified they are contained within the XML file I am connecting to - but I believe I've set my getVideos/setVideos parameters incorrectly and I'm not sure how they might be corrected.
XML Data
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<response>
<cmd>getVideos</cmd>
<success>1</success>
<NumberOfVideos>4</NumberOfVideos>
<Videos>
<Video>
<VideoName>sample_iPod</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/omv/wp-content/uploads/sites/6/2014/01/omv/1/06087297988b.m4v
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_mpeg4</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/omv/wp-content/uploads/sites/6/2014/01/omv/1/b5ed9e7100e2.mp4
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_sorenson</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/omv/wp-content/uploads/sites/6/2014/01/omv/1/2a8e64b24997.mov
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_iTunes</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/omv/wp-content/uploads/sites/6/2014/01/omv/1/6c7f65254aad.mov
</VideoUrl>
<VideoTags/>
</Video>
</Videos>
</response>
SAX Parser Related Java:
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("response")) {
// add it to the list
response.add(cmd);
} else if (qName.equalsIgnoreCase("success")) {
cmd.setSuccess(tempVal);
} else if (qName.equalsIgnoreCase("numberofvideos")) {
cmd.setNumberOfVideos(tempVal);
} else if (qName.equalsIgnoreCase("videos")) {
cmd.setVideos(tempVal);
} else if (qName.equalsIgnoreCase("video")) {
cmd.setVideo(tempVal);
} else if (qName.equalsIgnoreCase("videoname")) {
cmd.setVideoName(tempVal);
} else if (qName.equalsIgnoreCase("videourl")) {
cmd.setVideoURL(tempVal);
}
...
public class SAXXMLParser {
public static List<Cmd> parse(InputStream is) {
List<Cmd> response = null;
try {
// create a XMLReader from SAXParser
XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser()
.getXMLReader();
// create a SAXXMLHandler
SAXXMLHandler saxHandler = new SAXXMLHandler();
// store handler in XMLReader
xmlReader.setContentHandler(saxHandler);
// the process starts
xmlReader.parse(new InputSource(is));
// get the `Video list`
response = saxHandler.getResponse();
} catch (Exception ex) {
Log.d("XML", "SAXXMLParser: parse() failed");
ex.printStackTrace();
}
// return Laptop list
return response;
}
}
...
public class Cmd {
private String success;
private String cmd;
private String videos;
private String video;
private String numberofvideos;
private String videoname;
private String videourl;
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getNumberOfVideos() {
return numberofvideos;
}
public void setNumberOfVideos(String numberofvideos) {
this.numberofvideos = numberofvideos;
}
public String getVideos() {
return videos;
}
public void setVideos(String videos) {
this.videos = videos;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
public String getVideoName() {
return videoname;
}
public void setVideoName(String videoname) {
this.videoname = videoname;
}
public String getVideoURL() {
return videourl;
}
public void setVideoURL(String videourl) {
this.video = videourl;
}
Please let me know if any additional information is required. I will be happy to provide it.

Your code sets the member video instead of videourl in setvideourl method
public void setVideoURL(String videourl) {
this.video = videourl;<<----
This.videourl = videourl;
}

Related

Stream closed by resolving resource

I'm trying to implement an xsd validator for schemas, that using imports and includes. I took this answer for example.
Here is my validating method:
public void validate(String filePath, String schemaName) throws Exception
{
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setResourceResolver(new ResourceResolver());
Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.setErrorHandler(new MySAXParseErrorHandler());
validator.validate(new StreamSource(filePath));
}
LSInput (entirely the same):
public class LSInputImpl implements LSInput
{
private String publicId;
private String systemId;
public String getPublicId()
{
return publicId;
}
public void setPublicId(String publicId)
{
this.publicId = publicId;
}
public String getBaseURI()
{
return null;
}
public InputStream getByteStream()
{
return null;
}
public boolean getCertifiedText()
{
return false;
}
public Reader getCharacterStream()
{
return null;
}
public String getEncoding()
{
return null;
}
public String getStringData()
{
synchronized (inputStream) {
try {
byte[] input = new byte[inputStream.available()];
inputStream.read(input);
String contents = new String(input);
return contents;
} catch (IOException e) {
e.printStackTrace();
System.out.println("Exception " + e);
}
return null;
}
}
public void setBaseURI(String baseURI)
{
}
public void setByteStream(InputStream byteStream)
{
}
public void setCertifiedText(boolean certifiedText)
{
}
public void setCharacterStream(Reader characterStream)
{
}
public void setEncoding(String encoding)
{
}
public void setStringData(String stringData)
{
}
public String getSystemId()
{
return systemId;
}
public void setSystemId(String systemId)
{
this.systemId = systemId;
}
public BufferedInputStream getInputStream()
{
return inputStream;
}
public void setInputStream(BufferedInputStream inputStream)
{
this.inputStream = inputStream;
}
private BufferedInputStream inputStream;
public LSInputImpl(String publicId, String sysId, InputStream input)
{
this.publicId = publicId;
this.systemId = sysId;
this.inputStream = new BufferedInputStream(input);
}
}
ResourceResolver:
public class ResourceResolver implements LSResourceResolver
{
public LSInput resolveResource(String type, String namespaceURI,
String publicId, String systemId, String baseURI) {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(systemId);
return new LSInputImpl(publicId, systemId, resourceAsStream);
}
}
When I'm trying to validate xml with xsd that has only imports, it works fine. But when I split one schema with two by using include, process fails with IOException:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:159)
at java.io.BufferedInputStream.available(BufferedInputStream.java:410)
at LSInputImpl.getStringData(LSInputImpl.java:57)
at com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper.resolveEntity(DOMEntityResolverWrapper.java:130)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.resolveEntity(XMLEntityManager.java:1073)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.resolveDocument(XMLSchemaLoader.java:659)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.resolveSchemaSource(XSDHandler.java:2105)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1088)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1120)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:620)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540)
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:255)
at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:638)
at Main.validate(Main.java:54)
at Main.main(Main.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
org.xml.sax.SAXParseException; systemId: file:///C:/Users/adobryn/Java/sub/schema.xsd; lineNumber: 456; columnNumber: 73; src-resolve: Cannot resolve the name 'st_Term' to a(n) 'type definition' component.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4162)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4145)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1741)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(XSDElementTraverser.java:405)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseLocal(XSDElementTraverser.java:194)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.traverseLocalElements(XSDHandler.java:3618)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:633)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540)
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:255)
at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:638)
at Main.validate(Main.java:54)
at Main.main(Main.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Schema with include:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/schema" targetNamespace="http://www.w3.org/schema" elementFormDefault="qualified">
<xsd:include schemaLocation="st_Term.xsd"/>
<xsd:element name="Term" type="st_Term" minOccurs="0" maxOccurs="1"/>
</xsd:schema>
I think, there is something wrong with getStringData() method. How can I modify it? Thanks for your help!
The problem was, that included xsd also has an include, and ResourceResolver looked in resources folder for it, not resources/sub, where that subincluded xsd was. So, I took another example, that has path tracking, and it works now :) Please note, that schemaBasePath should start with "/"
I had the same problem with includes in .xsd several years ago.
As I can remember my problem was that .xsd resource and its includes were located in some package (directory) within resources.
I've solved it with the following ResourceResolver where the package is passed to constructor (resourceRoot argument):
class ResourceResolver implements LSResourceResolver {
private String resourceRoot;
public ResourceResolver(String resourceRoot) {
this.resourceRoot = resourceRoot;
}
public LSInput resolveResource(String type, String namespaceURI,String publicId, String systemId, String baseURI) {
InputStream resourceAsStream = this.getClass().getResourceAsStream(resourceRoot + "/" + systemId);
return new Input(publicId, systemId, resourceAsStream);
}
}
and Input:
static class Input implements LSInput {
private String publicId;
private String systemId;
public String getPublicId() {
return publicId;
}
public void setPublicId(String publicId) {
this.publicId = publicId;
}
public String getBaseURI() {
return null;
}
public InputStream getByteStream() {
return null;
}
public boolean getCertifiedText() {
return false;
}
public Reader getCharacterStream() {
return null;
}
public String getEncoding() {
return null;
}
public String getStringData() {
synchronized (inputStream) {
try {
byte[] input = new byte[inputStream.available()];
inputStream.read(input);
String contents = new String(input, "UTF-8");
return contents;
} catch (IOException e) {
e.printStackTrace();
System.out.println("Exception " + e);
return null;
}
}
}
public void setBaseURI(String baseURI) {
}
public void setByteStream(InputStream byteStream) {
}
public void setCertifiedText(boolean certifiedText) {
}
public void setCharacterStream(Reader characterStream) {
}
public void setEncoding(String encoding) {
}
public void setStringData(String stringData) {
}
public String getSystemId() {
return systemId;
}
public void setSystemId(String systemId) {
this.systemId = systemId;
}
private final BufferedInputStream inputStream;
public Input(String publicId, String sysId, InputStream input) {
this.publicId = publicId;
this.systemId = sysId;
this.inputStream = new BufferedInputStream(input);
}
}

JAXb not populating object during unmarshal

I am a bit lost at this point. I am by no means a SOAP/JAXb expert, however, I am trying to create a generic class that will marshal/call/unmarshal for any service. I am using the Weather Service wsdl as a starting point to prove out the concept.
I have finally gotten the marshalling, call and unmarshalling to execute without error, however, the response object is not being populated. Can anyone assist in identifying what I am doing incorrectly? I am also looking for a good explanation to the answer if possible so I can learn from this experience.
Again, there is no error while excuting. The issue is that the value of GetCityWeatherByZIPResponse.GetCityWeatherByZIPResult comes out to be null. I know the document is returning the correct results as the result printout is as follows:
Result printout:
<?xml version="1.0" encoding="UTF-8"?><GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/">
<GetCityWeatherByZIPResult>
<Success>true</Success>
<ResponseText>City Found</ResponseText>
<State>MO</State>
<City>Saint Charles</City>
<WeatherStationCity>Farmington</WeatherStationCity>
<WeatherID>4</WeatherID>
<Description>Sunny</Description>
<Temperature>79</Temperature>
<RelativeHumidity>47</RelativeHumidity>
<Wind>CALM</Wind>
<Pressure>30.00S</Pressure>
<Visibility/>
<WindChill/>
<Remarks/>
</GetCityWeatherByZIPResult>
</GetCityWeatherByZIPResponse>
Response: GetCityWeatherByZIPResult: null
Test Web Service:
http://wsf.cdyne.com/WeatherWS/Weather.asmx
Initial call (done via JBehave):
#Given("I call the weather soap service")
public void givenICallTheWeatherSoapService() {
GetCityWeatherByZIP weather = new GetCityWeatherByZIP();
weather.setZIP("63304");
try {
new WeatherTools();
WeatherSoap weatherSoap = new WeatherSoap();
GetCityWeatherByZIPResponse response = weatherSoap.getCityWeatherByZip("63304");
System.out.println("Response: " + response);
} catch (JAXBException | ParserConfigurationException | SOAPException | IOException e) {
Assert.fail(e.getMessage());
}
}
Soap Service Class:
public class WeatherSoap extends PTFSoapClient {
public WeatherSoap() throws JAXBException, ParserConfigurationException, SOAPException {
super(PTFApplication.getConfig(Environment.executionEnv.getEnv(), "Weather SOAP endpoint"));
}
public GetCityWeatherByZIPResponse getCityWeatherByZip(String zip) throws JAXBException, SOAPException, IOException {
GetCityWeatherByZIP weatherByZip = new GetCityWeatherByZIP();
weatherByZip.setZIP(zip);
try {
sendRequest(weatherByZip);
return (GetCityWeatherByZIPResponse) unmarshallResponse(GetCityWeatherByZIPResponse.class);
} catch (ParserConfigurationException | XMLStreamException e) {
e.printStackTrace();
return null;
}
}
}
Base Framework Class genericizing the call (usable for all SOAP calls):
public class PTFSoapClient {
private JAXBContext context;
private Marshaller marshaller;
private Object object;
private SOAPMessage message;
private String endpoint;
private SOAPMessage response;
public PTFSoapClient(String endpoint) {
this.endpoint = endpoint;
}
public void toConsole() throws JAXBException, SOAPException, IOException {
message.writeTo(System.out);
System.out.print("\n");
}
public SOAPMessage sendRequest(Object obj) throws JAXBException, ParserConfigurationException, SOAPException {
object = obj;
context = JAXBContext.newInstance(obj.getClass());
marshaller = context.createMarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().newDocument();
marshaller.marshal(object,doc);
MessageFactory factory = MessageFactory.newInstance();
message = factory.createMessage();
message.getSOAPBody().addDocument(doc);
message.saveChanges();
SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
response = connection.call(message, endpoint);
connection.close();
try {
System.out.println("Response:");
response.writeTo(System.out);
System.out.println("");
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
public Object unmarshallResponse(Class<?> classname) throws JAXBException, XMLStreamException, SOAPException, IOException {
Document doc = response.getSOAPBody().extractContentAsDocument();
try {
System.out.println("Document: ");
printDocument(doc, System.out);
System.out.println("");
} catch (TransformerException e) {
e.printStackTrace();
}
Unmarshaller unmarshaller = JAXBContext.newInstance(classname).createUnmarshaller();
return unmarshaller.unmarshal(doc);
}
public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}
}
Base unmarshal object:
#XmlRootElement(name = "GetCityWeatherByZIPResponse",
namespace = "http://ws.cdyne.com/WeatherWS/")
public class GetCityWeatherByZIPResponse {
GetCityWeatherByZIPResult GetCityWeatherByZIPResult;
public GetCityWeatherByZIPResult getGetCityWeatherByZIPResult() {
return GetCityWeatherByZIPResult;
}
public void setGetCityWeatherByZIPResult(GetCityWeatherByZIPResult GetCityWeatherByZIPResult) {
this.GetCityWeatherByZIPResult = GetCityWeatherByZIPResult;
}
#Override
public String toString() {
return "GetCityWeatherByZIPResult: " + GetCityWeatherByZIPResult;
}
}
Sub umarshal object:
public class GetCityWeatherByZIPResult {
boolean Success;
String ResponseText;
String State;
String City;
String WeatherStationCity;
String WeatherID;
String Description;
int Temperature;
int RelativeHumidity;
String Wind;
String Pressure;
String Visibility;
String WindChill;
String Remarks;
public boolean isSuccess() {
return Success;
}
public void setSuccess(boolean success) {
Success = success;
}
public String getResponseText() {
return ResponseText;
}
public void setResponseText(String responseText) {
ResponseText = responseText;
}
public String getState() {
return State;
}
public void setState(String state) {
State = state;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public String getWeatherStationCity() {
return WeatherStationCity;
}
public void setWeatherStationCity(String weatherStationCity) {
WeatherStationCity = weatherStationCity;
}
public String getWeatherID() {
return WeatherID;
}
public void setWeatherID(String weatherID) {
WeatherID = weatherID;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public int getTemperature() {
return Temperature;
}
public void setTemperature(int temperature) {
Temperature = temperature;
}
public int getRelativeHumidity() {
return RelativeHumidity;
}
public void setRelativeHumidity(int relativeHumidity) {
RelativeHumidity = relativeHumidity;
}
public String getWind() {
return Wind;
}
public void setWind(String wind) {
Wind = wind;
}
public String getPressure() {
return Pressure;
}
public void setPressure(String pressure) {
Pressure = pressure;
}
public String getVisibility() {
return Visibility;
}
public void setVisibility(String visibility) {
Visibility = visibility;
}
public String getWindChill() {
return WindChill;
}
public void setWindChill(String windChill) {
WindChill = windChill;
}
public String getRemarks() {
return Remarks;
}
public void setRemarks(String remarks) {
Remarks = remarks;
}
}
Your Current Mapping
When you specify the namespace property on the #XmlRootElement annotation, it only applies to that one element.
#XmlRootElement(name = "GetCityWeatherByZIPResponse",
namespace = "http://ws.cdyne.com/WeatherWS/")
public class GetCityWeatherByZIPResponse {
Your XML Document
Your XML document specifies a default namespace. This means that all elements without another explicit namespace mapping are also part of the http://ws.cdyne.com/WeatherWS/ namespace.
<?xml version="1.0" encoding="UTF-8"?><GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/">
<GetCityWeatherByZIPResult>
<Success>true</Success>
The Namespace Fix
You are going to want to specify the namespace mapping at the package level so that it applies to all your element mappings. This is done using the package level #XmlSchema annotation on a speciial class called package-info.
#XmlSchema(
namespace = "http://ws.cdyne.com/WeatherWS/",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
For More Information
I have written more about JAXB and namespace qualification on my blog:
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Update
Default Element Names
The default elements for your properties don't match your XML. for the property below the expected element name will be getCityWeatherByZIPResult so you will need to override the default using the #XmlElement annotation.
#XmlElement(name="GetCityWeatherByZIPResult")
public GetCityWeatherByZIPResult getGetCityWeatherByZIPResult() {
return GetCityWeatherByZIPResult;
}
Debugging Tip
When you encounter problems unmarshalling, populate your object model and marshal it to see what the expected XML is based on your current mappings.

XML parsing in android.not working

I have a few Java files that I have to try and get info from an XML on the internet. I made the files with the help of some tutorials online but I can't find the problem with what I have.
Below are the three classes I used.
MainXMLClass.java
public class News extends ActionBarActivity {
static final String baseURL = "http://coderdojo.com/rss.xml";
ListView News;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news);
getActionBar().setHomeButtonEnabled(true);
xmlRefs();
GetURLData();
ArrayList<String> XMLData = new ArrayList<>();
XMLData.add(XMLDataCollected.GetXMLData());
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.id.lvNews, XMLData);
News.setAdapter(adapter);
}
private void xmlRefs() {
// TODO Auto-generated method stub
News = (ListView) findViewById(R.id.lvNews);
}
private void GetURLData() {
// TODO Auto-generated method stub
try {
URL webPage = new URL(baseURL);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
XMLDataHandler Data = new XMLDataHandler();
reader.setContentHandler(Data);
reader.parse(new InputSource(webPage.openStream()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
My XMLHandler.java Class:
public class XMLDataHandler extends DefaultHandler {
XMLDataCollected Info = new XMLDataCollected();
public String getInformation() {
return XMLDataCollected.GetXMLData();
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (localName.equals("title")) {
String title = localName.getBytes().toString();
Info.setTitle(title);
} else if (localName.equals("link")) {
String link = localName.getBytes().toString();
Info.setLink(link);
} else if (localName.equals("description")) {
String description = localName.getBytes().toString();
Info.setDescription(description);
}
}
}
And finally my XMLDataCollected.java class:
public class XMLDataCollected {
static String title;
static String description;
static String link;
public void setTitle(String t) {
title = t;
}
public void setDescription(String d) {
description = d;
}
public void setLink(String l) {
link = l;
}
public static String GetXMLData() {
return title + description + link;
}
}
I've been trying for about three days to get this sorted but so far I haven't been able to find a solution anywhere.
This is my first time trying to use XML parsing so I'm aware there is bound to be a few things wrong with the files but any help is appreciated.
I may be missing something, but are you SURE about that URL, as I understand, this is the final URL : http://coderdojo.com/news?page=0 or some other number. But when I typed into the browser, the result is not XML format.

SAXParser catch nothing with minimized XML document

I'm running a small Android project which could read RSS/Atom Feed documents, using SAX library. Everything works well for default RSS sources, but with minimized sources (without spaces or new line tokens), it produces nothing but a list of blank items. My logs in Log cat also display nothing. I double check this problems with variant RSS sites, but problems still there. Below is my inheritance class of DefaultHandler which I use to handle Rss sources
public class RssContentHandler extends DefaultHandler {
private static final int UNKNOWN_STATE = -1;
private static final int ELEMENT_START = 0;
private static final int TITLE_END = 1;
private static final int DESCRIPTION_END = 2;
private static final int LINK_END = 3;
private static final int PUBDATE_END = 4;
private static final int CHANNEL_END = 5;
private int iState = UNKNOWN_STATE;
private String fullCharacters;
private boolean itemFound = false;
private RssItem rssItem;
private RssFeed rssFeed;
public RssContentHandler() {
}
public RssFeed getFeed() {
return this.rssFeed;
}
#Override
public void startDocument() {
rssItem = new RssItem();
rssFeed = new RssFeed();
Log.i("startDocument", "startDocument");
}
#Override
public void endDocument() {
}
#Override
public void startElement(String _uri, String _localName, String _qName, Attributes _attributes) {
if (_localName.equalsIgnoreCase("item")) {
itemFound = true;
rssItem = new RssItem();
this.iState = UNKNOWN_STATE;
} else
this.iState = ELEMENT_START;
fullCharacters = "";
}
#Override
public void endElement(String _uri, String _localName, String _qName) {
if (_localName.equalsIgnoreCase("item"))
this.rssFeed.addItem(this.rssItem);
else if (_localName.equalsIgnoreCase("title"))
this.iState = TITLE_END;
else if (_localName.equalsIgnoreCase("description"))
this.iState = DESCRIPTION_END;
else if (_localName.equalsIgnoreCase("link"))
this.iState = LINK_END;
else if (_localName.equalsIgnoreCase("pubDate"))
this.iState = PUBDATE_END;
else if (_localName.equalsIgnoreCase("channel"))
this.iState = CHANNEL_END;
else
this.iState = UNKNOWN_STATE;
}
#Override
public void characters(char[] _ch, int _start, int _length) {
String strCharacters = new String(_ch, _start, _length);
if (this.iState == ELEMENT_START)
fullCharacters += strCharacters;
else {
if (!itemFound) {
switch (this.iState) {
case TITLE_END:
this.rssFeed.setTitle(fullCharacters);
break;
case DESCRIPTION_END:
this.rssFeed.setDescription(fullCharacters);
break;
case LINK_END:
this.rssFeed.setLink(fullCharacters);
break;
case PUBDATE_END:
this.rssFeed.setPubDate(fullCharacters);
break;
}
} else {
switch (this.iState) {
case TITLE_END:
this.rssItem.setTitle(fullCharacters);
Log.i("characters", fullCharacters);
break;
case DESCRIPTION_END:
this.rssItem.setDescription(fullCharacters);
break;
case LINK_END:
this.rssItem.setLink(fullCharacters);
break;
case PUBDATE_END:
this.rssItem.setPubDate(fullCharacters);
break;
}
}
this.iState = UNKNOWN_STATE;
}
}
}
and snippet to setup the parser:
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
try {
request.setURI(new URI(_strUrl));
} catch (URISyntaxException e) {
e.printStackTrace();
}
HttpResponse response = client.execute(request);
Reader inputStream = new InputStreamReader(response.getEntity().getContent());
RssContentHandler rssContentHandler = new RssContentHandler();
InputSource inputSource = new InputSource();
inputSource.setCharacterStream(inputStream);
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.parse(inputSource, rssContentHandler);
this.rssFeed = rssContentHandler.getFeed();
P/s: i'm using Android 2.3 x86 installed on VirtualBox for Debugging, and these sources work fine with the built-in RSS Reader app come with the x86 version. So what's wrong here?
Try with _qName instead of _localName.
Your xml contains CDATA so You cann't parse the XML response with your current parser. You have to use LexicalHandler for parsing Raw HTML.
public class MyHandler implements LexicalHandler {
public void startDTD(String name, String publicId, String systemId)
throws SAXException {}
public void endDTD() throws SAXException {}
public void startEntity(String name) throws SAXException {}
public void endEntity(String name) throws SAXException {}
public void startCDATA() throws SAXException {}
public void endCDATA() throws SAXException {}
public void comment (char[] text, int start, int length)
throws SAXException {
String comment = new String(text, start, length);
System.out.println(comment);
}
You can also parse your XML with DOM if memory is not the issue. For more help visit Handling Lexical Events

parsing xml file from network database in android

i am trying to parse an xml file from an URL. I found an example in the following link
http://www.anddev.org/parsing_xml_from_the_net_-_using_the_saxparser-t353.html
and tried using it in my code but it returned the values to be as null
Following is my code of parsing xml
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
URL url = new URL("http://www.siva.com/search");
/** Handling XML */
SAXParserFactory saxparserfactory = SAXParserFactory.newInstance();
SAXParser saxparser = saxparserfactory.newSAXParser();
XMLReader xmlreader = saxparser.getXMLReader();
/* Create a new ContentHandler and apply it to the XML-Reader*/
ForListXMLHandler forlistmyhandler = new ForListXMLHandler();
xmlreader.setContentHandler(forlistmyhandler);
/* Parse the xml-data from our URL. */
xmlreader.parse(new InputSource(url.openStream()));
/* Parsing has finished. */
/* Our ExampleHandler now provides the parsed data to us. */
ParsedDataSet parsedDataSet = forlistmyhandler.getParsedData();
System.out.println(parsedDataSet.toString());
}
following is the code of MyXMLhandler
public class ForListXMLHandler extends DefaultHandler {
private boolean in_outertag = false;
private boolean in_innertag = false;
private boolean in_First_name = false;
private boolean in_Last_name = false;
private ParsedDataSet myParsedDataSet = new ParsedDataSet();
public ParsedDataSet getParsedData() {
return this.myParsedDataSet;
}
#Override
public void startDocument() throws SAXException {
this.myParsedDataSet = new ParsedDataSet();
}
#Override
public void endDocument() throws SAXException {
// Nothing to do
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
if (localName.equals("Searchdata")) {
this.in_outertag = true;
} else if (localName.equals("Searchdata")) {
this.in_innertag = true;
} else if (localName.equals("First_name")) {
this.in_First_name = true;
} else if (localName.equals("Last_name")) {
this.in_Last_name = true;
}
}
/**
* Gets be called on closing tags like:
* */
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if (localName.equals("Searchdata")) {
this.in_outertag = false;
} else if (localName.equals("Searchdata")) {
this.in_innertag = false;
} else if (localName.equals("First_name")) {
this.in_First_name = false;
} else if (localName.equals("Last_name")) {
// Nothing to do here
}
}
/**
* Gets be called on the following structure: characters
*/
#Override
public void characters(char ch[], int start, int length) {
if (this.in_First_name) {
myParsedDataSet.setfirstname(new String(ch, start, length));
}
if (this.in_Last_name) {
myParsedDataSet.setlastname(new String(ch, start, length));
}
}
}
next part is of my parsed data set class
public class ParsedDataSet {
private String First_name = null;
private String Last_name = null;
public String getFirstname() {
return First_name;
}
public void setfirstname(String First_name) {
this.First_name = First_name;
}
public String getlastname() {
return Last_name;
}
public void setlastname(String Last_name) {
this.Last_name = Last_name;
}
public String toString() {
return this.First_name + "n" + this.Last_name;
}
}
pls tell me where i am getting error
The endElement method gets fired before the characters method, so your boolean variables are always set to false when the characters method gets fired. You should move some code from endElement to characters, something like this:
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
}
#Override
public void characters(char ch[], int start, int length) {
if (this.in_First_name) {
this.in_First_name = false;
myParsedDataSet.setfirstname(new String(ch, start, length));
}
if (this.in_Last_name) {
this.in_Last_name = false;
myParsedDataSet.setlastname(new String(ch, start, length));
}
}
You should also take a look here for a complete explanation on "Working with XML on Android".

Categories