Android XML parsing with XmlPullParse - java

I am new to XML to parsing and dont know how to go about getting certain details from an xml file. In the following code, (Android Java) I get the location from the tag. Very straight forward;
public void readXML(String xmlToRead) throws XmlPullParserException {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(xmlToRead));
WeatherDetails weatherDetails = new WeatherDetails();
xpp.next();
int eventType = xpp.getEventType();
while (xpp.getEventType()!=XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType()==XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("description")) {
weatherDetails.setWeatherLocation(xpp.nextText());
weather_userlocation.setText(weatherDetails.getWeatherLocation());
}
}
xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Here is an example XML I'm attempting to parse:
http://forecast.weather.gov/MapClick.php?lat=40.28331&lon=-84.1435136&unit=0&lg=english&FcstType=dwml
Near the bottom of the XML, there is a segment:
<parameters applicable-location="point1">
<temperature type="apparent" units="Fahrenheit" time-layout="k-p1h-n1-1">
<value>33</value>
</temperature>
The value I want is inside the value tag, but there are numerous value tags throughout the XML. How can I point and retrieve this specific one?
Thank you all!
Heres my implementation of your suggestion:
while (xpp.getEventType()!=XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType()==XmlPullParser.START_TAG) {
String name = xpp.getName();
if (name.equalsIgnoreCase("description")) {
weatherDetails.setWeatherLocation(xpp.nextText());
weather_userlocation.setText(weatherDetails.getWeatherLocation());
}
if(name.equalsIgnoreCase("temperature")) {
weather_apparenttemp.setText("Found TEMPERATURE tag!");
xpp.next();
if(xpp.getName().equals("value")) {
weather_apparenttemp.setText(xpp.nextText());
}
}
}
xpp.next();
}

what you need to do is search until you find the temperature tag using something like
String name = xpp.getName();
if(name.equals("temperature"))
{
if(xpp.next().equals("value")
{ String temp = xpp.next.getValue()}
}
Not 100%sure on the synax, its been a while since I used this but that should be the general idea.
Another alternative is to call another function that takes the parser as a parameter and then you can search within that, but thats more for if you have odd structure to the xml.

Related

How can I write an XML string in Stax without duplicating namespaces

Part way through creating an XML file with Stax I have some XML in the form of a String. I write this to the Stax output using:
public void addInnerXml(String xml) throws TinyException {
try {
parent.adjustStack(this);
XMLStreamReader2 sr = (XMLStreamReader2) ifact.createXMLStreamReader(new ByteArrayInputStream(xml.getBytes("UTF8")));
for (int type = sr.getEventType(); sr.hasNext(); type = sr.next()) {
switch (type) {
case XMLStreamConstants.COMMENT:
case XMLStreamConstants.DTD:
case XMLStreamConstants.START_DOCUMENT:
case XMLStreamConstants.END_DOCUMENT:
continue;
}
parent.getWriter().copyEventFromReader(sr, false);
}
sr.close();
} catch (XMLStreamException e) {
throw new TinyException("addInnerXml", e);
} catch (UnsupportedEncodingException e) {
throw new TinyException("addInnerXml", e);
}
}
It all works great except namespaces used in the passed in XML, that are defined in the root element, are duplicated again in the inner nodes. Note that the p prefix is repeated
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<p:cSld> <p:spTree> <p:pic
xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
Is there a way to turn this off?
notes: XMLStreamReader2 implements org.codehaus.stax2.typed.TypedXMLStreamReader and is actually XMLStreamReader.
parent.getWriter() also returns an XMLStreamReader2.
thanks - dave

Jsoup.connect().get() takes only part of html file on Android

So, I try to parse Wikipedia, and my code works well at computer.
All, what I changed - .connect().get is in AsyncTask, but I get only part of html file (no "body", only half of second "script" in "title") and I can't understand why.
This is my code example for Android.
protected String doInBackground(String... params) {
try {
Document doc = Jsoup.connect(params[0]).get();
return doc.toString();
} catch (IOException e) {
//...
e.printStackTrace();
}
return null;
}
And this is simple.
String url = "https://en.wikipedia.org/wiki/Protectorate";
Document doc = null;
try {
doc = Jsoup.connect(url).get();
} catch (IOException e) {
//...
e.printStackTrace();
}
I checked, params[0] is https://en.wikipedia.org/wiki/Protectorate, here's no mistake.
If you need some extra information, I will give it, of course.
Logcat fools us here, since it shortens the message (I assume you checked your string with logcat? See related question)
If you split your result string into chunks, you will see that the whole page was loaded. Try adding something like this logAll function to your AsyncTask class to see the full output:
private class DownloadTask extends AsyncTask<String, Integer, String> {
Document doc = null;
protected String doInBackground(String... params) {
try {
doc = Jsoup.connect(params[0]).get();
return doc.toString();
} catch (Exception e) {
e.printStackTrace();
}
return doc.toString();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
logAll("async",doc.toString());
}
void logAll(String TAG, String longString) {
int splitSize = 300;
if (longString.length() > splitSize) {
int index = 0;
while (index < longString.length()-splitSize) {
Log.e(TAG, longString.substring(index, index + splitSize));
index += splitSize;
}
Log.e(TAG, longString.substring(index, longString.length()));
} else {
Log.e(TAG, longString.toString());
}
}
}

JAVA - Converting android application into fragment styled application

My app has main.xml and MainActivity. I wanted to convert it to a tabbed styled app. By the help of this tutorial, I've successfully made a UI with a tabbed style.
Now I have to put the codes in my MainActivty(not tabbed style) to the fragments. i don't know how to do it. when i just put the codes to my ToolsFragment.java, it doesn't work.
Here are my codes:
//To get ip address using netcfg
private String ipnc()
{
int e = doNETCFG().indexOf("10.");
if (e == -1)
{
return "";
}
else
{
String ipnc1 = doNETCFG().substring(e, e + 15);
String ipnc2[] = ipnc1.split("/");
String ipnc3 = ipnc2[0];
return ipnc3;
}
}
//To generate netcfg from command line
public String doNETCFG()
{
String str = null;
try
{
Process localProcess = Runtime.getRuntime().exec("/system/bin/netcfg");
BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(localProcess.getInputStream()));
char[] arrayOfChar = new char[4096];
StringBuffer localStringBuffer = new StringBuffer();
while (true)
{
int i = localBufferedReader.read(arrayOfChar);
if (i <= 0)
{
localBufferedReader.close();
localProcess.waitFor();
str = localStringBuffer.toString();
break;
}
localStringBuffer.append(arrayOfChar, 0, i);
}
}
catch (IOException localIOException)
{
Log.e("TAG", localIOException.getStackTrace().toString());
}
catch (InterruptedException localInterruptedException)
{
Log.e("TAG", localInterruptedException.getStackTrace().toString());
}
return str;
}
//To enable/disable mobile data
private void setMobileDataEnabled(Context context, boolean enabled)
{
final ConnectivityManager conman;
conman =
(ConnectivityManager)context.getSystemService
(Context.CONNECTIVITY_SERVICE);
final Class conmanClass;
try
{
conmanClass =
Class.forName(conman.getClass
().getName());
final Field
iConnectivityManagerField =
conmanClass.getDeclaredField
("mService");
iConnectivityManagerField.
setAccessible(true);
final Object
iConnectivityManager =
iConnectivityManagerField.get
(conman);
final Class
iConnectivityManagerClass =
Class.forName
(iConnectivityManager.getClass
().getName());
final Method
setMobileDataEnabledMethod =
iConnectivityManagerClass.
getDeclaredMethod
("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.
setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, enabled);
}
catch
(ClassNotFoundException e)
{
e.printStackTrace();
}
catch
(InvocationTargetException e)
{
e.printStackTrace();
}
catch
(NoSuchMethodException e)
{
e.printStackTrace();
}
catch
(IllegalAccessException e)
{
e.printStackTrace();
}
catch
(NoSuchFieldException e)
{
e.printStackTrace();
}
}
//To play success alert tone
public void playAlertTone()
{
new Thread()
{
public void run()
{
int i = 0;
while (true)
{
if (i >= 1)
return;
MediaPlayer localMediaPlayer = MediaPlayer.create(getApplicationContext(), 0x7f040000);
localMediaPlayer.start();
i++;
try
{
Thread.sleep(100 + localMediaPlayer.getDuration());
localMediaPlayer.release();
}
catch (InterruptedException localInterruptedException)
{
}
}
}
}
.start();
}
What should I do? Do I have to put this into another activity and call it in fragment? If that's the case, how?
Or convert it to a code executable in fragments and run it there? How can I do this?
I'm a newbie in android programming. Thanks!
when you convert an application to fragment based structure, you have to consider one thing that the context is same for all the fragments in an activity. You will get it by calling getActivity(). So save your context first and use it where ever you want the context.
From your question you are developing an application with tabs. So you may have to create fragments as many as the tabs. You can put your code for each tab in the corresponding fragment.
Now to communicate between the fragments the best way is to use callbacks in your parent activity.
A simple tutorial for implementing fragments can be found HERE
The communication between fragments is explained HERE
Fragments do most of the things activities do. The reason why they were introduced (one of the reasons at least) was so you can place the code in them instead of in the activities of your app. If you think this way, you will notice that you will only need a small number of activities.
I am not sure what you mean by "convert it to a code executable in fragments". You can place your code inside your fragments (use methods) and then simply call those methods.
If you are not sure how Fragments work, I would highly recommend reading the documentation.
I hope this gives you an idea of how to get your code to work in fragments.

Advice for Simplifying code to Load an XML file?

I finally finished my XML parsing code, and now looking at it, it scares me. This code is for a simple Android-based, text adventure game.
I have all my data about encounters, locations, and characters stored in XML files in the 'res' folder.
I coded this XML parser to go through the XML files and store data into a class called Encounter. I can then access the data inside Encounter anywhere in my code.
So I guess I got the OOP part down. But the actual parsing just looks so messy.
Is there a better way to go about parsing XML data?
Here is my code:
public class XmlParser extends Activity {
private String xmlValue;
private int encounterID;
Encounter encounter;
public XmlParser()
throws XmlPullParserException, IOException
{
XmlPullParser xpp = getResources().getXml(R.xml.encounters);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String elName = xpp.getName();
if(eventType == XmlPullParser.START_TAG) { //creature
eventType = xpp.next();
//top level nodes
if(xpp.getName().equalsIgnoreCase("identity")){
eventType = xpp.next();
if(elName.equalsIgnoreCase("name")) {
encounter.name = xpp.getText();
} else if(elName.equalsIgnoreCase("race")) {
encounter.race = xpp.getText();
} else if(elName.equalsIgnoreCase("gender")) {
encounter.gender = xpp.getText();
} else if(elName.equalsIgnoreCase("alignment")) {
encounter.alignment = xpp.getText();
} else if(elName.equalsIgnoreCase("age")) {
try {
encounter.age = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
}
} else if (xpp.getName().equalsIgnoreCase("appearance")) {
eventType = xpp.next();
if(elName.equalsIgnoreCase("condition")){
encounter.condition = xpp.getText();
} else if(elName.equalsIgnoreCase("skinColor")) {
encounter.skinColor = xpp.getText();
} else if(elName.equalsIgnoreCase("hairColor")) {
encounter.hairColor = xpp.getText();
} else if(elName.equalsIgnoreCase("size")) {
encounter.size = xpp.getText();
} else if(elName.equalsIgnoreCase("height")) {
encounter.height = xpp.getText();
} else if(elName.equalsIgnoreCase("weight")) {
encounter.weight = xpp.getText();
}
} else if (xpp.getName().equalsIgnoreCase("stats")) {
eventType = xpp.next();
if(elName.equalsIgnoreCase("hitPoints")) {
try {
encounter.HP = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
} else if(elName.equalsIgnoreCase("armorClass")) {
try {
encounter.AC = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
} else if(elName.equalsIgnoreCase("actionPoints")) {
try {
encounter.AP = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
} else if(elName.equalsIgnoreCase("magicPoint")) {
try {
encounter.AP = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
} else if(elName.equalsIgnoreCase("strength")) {
try {
encounter.strength = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
} else if(elName.equalsIgnoreCase("dexterity")) {
try {
encounter.dexterity = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
} else if(elName.equalsIgnoreCase("intelligence")) {
try {
encounter.intelligence = Integer.parseInt(xpp.getText());
} catch (NumberFormatException e) {
//ok
}
}
} else if (xpp.getName().equalsIgnoreCase("inventory")) {
eventType = xpp.next();
if(elName.equalsIgnoreCase("weapon")) {
encounter.weapon = xpp.getText();
} else if(elName.equalsIgnoreCase("armor")) {
encounter.armor = xpp.getText();
} else if(elName.equalsIgnoreCase("magicItem")) {
encounter.magicItem = xpp.getText();
}
} else if (xpp.getName().equalsIgnoreCase("magic")) {
eventType = xpp.next();
if(elName.equalsIgnoreCase("attackSpell")) {
encounter.attackSpell = xpp.getText();
} else if(elName.equalsIgnoreCase("defenseSpell")) {
encounter.defenseSpell = xpp.getText();
}
} else if (xpp.getName().equalsIgnoreCase("treasureItems")) {
eventType = xpp.next();
if(elName.equalsIgnoreCase("item1")) {
encounter.item1 = xpp.getText();
} else if(elName.equalsIgnoreCase("item2")) {
encounter.item2 = xpp.getText();
}
}
} else if(eventType == XmlPullParser.END_TAG) {
//System.out.println("End tag "+xpp.getName());
}
eventType = xpp.next();
}
//System.out.println("End document");
}
In case anyone is interested, here is my XML file for encounters:
<?xml version="1.0" encoding="UTF-8"?>
<encounters>
<creature id="1" type="monster">
<identity>
<name></name>
<race></race>
<gender></gender>
<age></age>
<alignment></alignment>
</identity>
<appearance>
<condition></condition>
<skinColor></skinColor>
<hairColor></hairColor>
<size></size>
<height></height>
<weight></weight>
</appearance>
<stats>
<hitPoints></hitPoints>
<armorClass></armorClass>
<actionPoints></actionPoints>
<magicPoints></magicPoints>
<strength></strength>
<dexterity></dexterity>
<intelligence></intelligence>
</stats>
<inventory>
<weapon></weapon>
<armor></armor>
<magicItem></magicItem>
</inventory>
<magic>
<attackSpell></attackSpell>
<defenseSpell></defenseSpell>
</magic>
<treasureItems>
<item1></item1>
<item2></item2>
</treasureItems>
</creature>
When dealing with XML that has a direct object mapping, as in your case, I usually tend to use a marshalling technology. The most standard nowadays is JAXB. However it add quite a bit overhead (aprox 9 megs) to your application, which is not negligible in a mobile application. In this case a more lightweight marshalling API such as simple, can have a niche.
You can check out VTD-XML, the lightweight library works
excellent with android (the larger does too, but it is much larger in filesize).
There is also the SAX-parser that comes with android.
Other than that, when I use the XmlPullParser, I usually have a map with the tagnames as keys and integers, then I can just get the value from the map and then use a simple switch, which clears up the code a bit:
//Before parsing, or if used frequently the map can be put outside the method and reused:
final HashMap<String, Integer> tags = new HashMap<String, Integer>(9, 1);
tags.put("encounters", 0);
tags.put("identity", 1);
tags.put("name", 2);
//And so on...
//in your parse-loop:
int tag = tags.get(xpp.getName());
switch(tag){
case 0: //Handle encounter tag...
break;
case 1: //Handle identity tag...
break;
case 2: //Handle name tag...
break;
//For all tags.
}

Call a web service and parse xml response in blackberry

Currently I have a ready design for blackberry application.
Now, I need to call the web service in my app, and that web service will give me some xml response.
So, I need to parse that response from xml to some POJO.
So, for parsing the xml response should I go with the basic DOM praser, or should I use any other J2ME specific prasing concept ?
If anybody have any sample tutorial link for the same then it would be very much useful to me.
Thanks in advance....
It depends on what your web service serves.
If it is REST-based, you're likely responsible to parse the XML yourself, with a library. I've only ever used kXml 2, a J2ME library that can be used on BlackBerry devices. To use it, it's best to link to the source (otherwise, you have to preverify the jar and export it and that never seems to work for me). It's a forward-only pull parser, similar to XmlReader in .NET, if you're familiar with that.
If your web service is WS*-based (i.e. it uses SOAP), you can use a stub generator to generate a client class that you can use. BlackBerry supports JSR 172, the web services API for J2ME. The WTK has a stub generator that works well. Just point the generator to your web service's wsdl file. A web search should clarify how to use it.
Add your xml file data in to strXML
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
Document document = builder.parse( inputStream );
Element rootElement = document.getDocumentElement();
rootElement.normalize();
blnViewReport=false;
listNodes(rootElement); // use this function to parse the xml
inputStream.close();
void listNodes(Node node)
{
Node tNode;
String strData;
String nodeName = node.getNodeName();
if( nodeName.equals("Tagname"))
{
tNode=node.getFirstChild();
if(tNode.getNodeType() == Node.TEXT_NODE)
{
// here you get the specified tag value
}
}
else if(nodeName.equals(“Tag name 2”))
.....
.....
NodeList list = node.getChildNodes();
if(list.getLength() > 0)
{
for(int i = 0 ; i<list.getLength() ; i++)
{
listNodes(list.item(i));
}
}
}
I believe that you have recieved the request object.
I will give the code I used to parse the request object from XML.
_value is the object
System.out.println("value="+_value);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = null; // create a parser
try {
parser = factory.newSAXParser();
}
catch (ParserConfigurationException e1)
{
System.out.println("ParserConfigurationException"+e1.getMessage());
}
catch (SAXException e1)
{
System.out.println("SAXException"+e1.getMessage());
}
// instantiate our handler
PharmacyDataXMLHandler pharmacydataXMLHandler= new PharmacyDataXMLHandler();
ByteArrayInputStream objBAInputStream = new java.io.ByteArrayInputStream(_value.getBytes());
InputSource inputSource = new InputSource(objBAInputStream);
// perform the synchronous parse
try {
parser.parse(inputSource, pharmacydataXMLHandler);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
_pharmacydataList = pharmacydataXMLHandler.getpharmacydataList();
}
public class PharmacyDataXMLHandler extends DefaultHandler
{
private Vector _pharmacyDataList = new Vector();
PharmacyData _pharmacydata;
StringBuffer _sb = null;
public void warning(SAXParseException e) {
System.err.println("warning: " + e.getMessage());
}
public void error(SAXParseException e) {
System.err.println("error: " + e.getMessage());
}
public void fatalError(SAXParseException e) {
System.err.println("fatalError: " + e.getMessage());
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
try{
_sb = new StringBuffer("");
if(localName.equals("Table"))
{
_pharmacydata= new PharmacyData();
}
}catch (Exception e) {
System.out.println(""+e.getMessage());
}
}
public void endElement(String namespaceURI, String localName, String qName) throws SAXException
{
try{
if(localName.equals("ID"))
{
// System.out.println("Id :"+sb.toString());
this._pharmacydata.setId(_sb.toString());
}
else if(localName.equals("Name"))
{
//System.out.println("name :"+sb.toString());
this._pharmacydata.setName(_sb.toString());
}
else if(localName.equals("PharmacyID"))
{
// System.out.println("pharmacyId :"+sb.toString());
this._pharmacydata.setPharmacyId(_sb.toString());
}
else if(localName.equals("Password"))
{
// System.out.println("password :"+sb.toString());
this._pharmacydata.setPassword(_sb.toString());
}
else if(localName.equals("Phone"))
{
// System.out.println("phone:"+sb.toString());
this._pharmacydata.setPhone(_sb.toString());
}
else if(localName.equals("Transmit"))
{
//System.out.println("transmit"+sb.toString());
this._pharmacydata.setTransmit(_sb.toString());
}
else if(localName.equals("TimeZone"))
{
// System.out.println("timeZone"+sb.toString());
this._pharmacydata.setTimeZone(_sb.toString());
}
else if(localName.equals("FaxModem"))
{
// System.out.println("faxModem"+sb.toString());
this._pharmacydata.setFaxModem(_sb.toString());
}
else if(localName.equals("VoicePhone"))
{
// System.out.println("voicePhone"+sb.toString());
this._pharmacydata.setVoicePhone(_sb.toString());
}
else if(localName.equals("ZipCode"))
{
// System.out.println("zipCode"+sb.toString());
this._pharmacydata.setZipCode(_sb.toString());
}
else if(localName.equals("Address"))
{
// System.out.println("address"+sb.toString());
this._pharmacydata.setAddress(_sb.toString());
}
else if(localName.equals("City"))
{
// System.out.println("city"+sb.toString());
this._pharmacydata.setCity(_sb.toString());
}
else if(localName.equals("State"))
{
// System.out.println("state"+sb.toString());
this._pharmacydata.setState(_sb.toString());
}
else if(localName.equals("WebInterface"))
{
// System.out.println("webInterface"+sb.toString());
this._pharmacydata.setWebInterface(_sb.toString());
}
else if(localName.equals("NABPnumber"))
{
// System.out.println("nabPnumber"+sb.toString());
this._pharmacydata.setNabPnumber(_sb.toString());
}
else if(localName.equals("ServiceType"))
{
// System.out.println("serviceType:"+sb.toString());
this._pharmacydata.setServiceType(_sb.toString());
}
else if(localName.equals("Mobile"))
{
// System.out.println("mobile:"+sb.toString());
this._pharmacydata.setMobile(_sb.toString());
}
else if(localName.equals("Table"))
{
// System.out.println("end table:"+sb.toString());
_pharmacyDataList.addElement(_pharmacydata);
}
}catch (Exception e) {
System.out.println(""+e.getMessage());
}
}
public void characters(char ch[], int start, int length) {
String theString = new String(ch, start, length);
_sb.append(theString);
}
/**
* #return the PharmacyDataList
*/
public Vector getpharmacydataList()
{
return _pharmacyDataList;
}
}

Categories