Android: using getname() of XMLPullParser - android

I'm using a XmlPullParser to read a xml file.
My file has the following line:
<Circle>
<Circle time="2015-12-21">
And my problem is on the second line, because I'm using getname() but it only returns Circle instead of returning Circle time="2015-12-21".
My code:
URL url = new URL(site);
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser()
while (xpp.next() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
continue;
}
name = xpp.getName();
if (name.equals("Circle time=\""+getDate()+"\"")) {
Log.d("Example","Success!!");
}
}
name is always Circle instead of Circle time="2015-12-21".
Can you please help me?

time is an attribute. To retrieve its value you can use
[getAttributeValue(java.lang.String, java.lang.String)][1]. getName returns the name of the current tag.
String name = xpp.getName();
if ("Circle".equals(name)) {
String time = xpp.getAttributeValue(null, "time");
// here time contains the content of the attribute
// you can compare it with getDate();
}
[1]: https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html?hl=es#getAttributeValue(java.lang.String, java.lang.String)

Related

Parsing complex XML using XmlPullParser

I'm facing the problem of parsing xml using XmlPullParser. Everithing works fine except this problmatic part:
<Device>
<Description>
Tracker, type CONNECT
<Firmware>0240</Firmware>
</Description>
<Settings>
...
</Settings>
<Variables>
...
</Variables>
</Device>
I need to parse both DESCRIPTION and FIRMWARE. But I can't read properly that description text because of such tags weird structure.
What I've tried (following this guide):
private Device parseDevice(XmlPullParser parser) throws XmlPullParserException, IOException {
Device device = new Device();
parser.require(XmlPullParser.START_TAG, ns, DEVICE);
//device.setDescription(readDeviceDescription(parser)); <---tried to parse from here
device.setName(readDeviceName(parser));
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// Starts by looking for the entry tag
switch (name) {
case DESCRIPTION:
// device.setDescription(readDeviceDescription(parser)); <---and from here
device.setFirmware(readDescription(parser, device)); //<-- and inside this method
break;
case VARIABLES:
device.setGroups(readGroups(parser));
break;
default:
skip(parser);
break;
}
}
return device;
}
readDeviceDesscription() method (maybe problem lies here):
private String readDeviceDescription(XmlPullParser parser) throws XmlPullParserException, IOException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.next();
}
return result;
}
But any my attempt was ending with returning null either to Firmware or to Description.
Please help. Appreciate any hint.
You should do:
private String readDeviceDescription(XmlPullParser parser) throws XmlPullParserException, IOException {
String result = parser.getText();
return result;
}
Since you are already positioned at Description start_tag getText call will return the text inside Description tag.
To get the Firmware tag text you should do:
if(parser.getEventType() == XmlPullParser.START_TAG && parser.getName().compareTo("Firmware")==0)
String firmwareText = parser.getText();
Also take a look at this its a good example of a clean XmlPullParser implementation.
Hope this helps.

How to parse Nested tag with same name using XMLpullparser in android

I want to parse title and link tag only in item section with XMLpullparser. how do i parse it with ignoring previous title and link tag?
<channel>
<title>AAA</title>
<link>linkone</link>
<item>
<title>BBB</title>
<link>link2</link>
</item>
</channel>
The parser which i am using currently is following. How do ignore starting title and link tag?
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
FileInputStream fis = ctx.openFileInput("StackSites.xml");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
xpp.setInput(reader);
int eventtype = xpp.getEventType();
while (eventtype != XmlPullParser.END_DOCUMENT){
String tagname = xpp.getName();
switch (eventtype){
case XmlPullParser.START_TAG:
if(tagname.equalsIgnoreCase("item")){
curStackSite = new StackSite();
}
break;
case XmlPullParser.TEXT:
curText = xpp.getText();
break;
case XmlPullParser.END_TAG:
if(tagname.equalsIgnoreCase("item")){
stackSites.add(curStackSite);
}
if(tagname.equalsIgnoreCase("title")){
curStackSite.setName(curText);
}
if(tagname.equalsIgnoreCase("link")){
curStackSite.setLink(curText);
}
break;
default:
break;
}
eventtype = xpp.next();
}
I dont know wheather its right way to do it, but what i did is inside case XmlPullParser.START_TAG: if it found item tag , ive set counter is equal to 1. and in case XmlPullParser.END_TAG: if counter != 0, then only it adds value to object .this method works. if anybody knows more accurate way please post. Thanks.
There is one library available to parse xml response to POJO class.
https://github.com/stanfy/gson-xml
By using this library, you do not need to do manual parsing. You need to create POJO class according to your xml.
For given xml, you need to create two POJO classes
Channel.java
public class Channel {
Item item;
}
Item.java
public class Item {
String title;
String link;
}
Now you can parse your xml like below
public void parseXml(Strng xml){
XmlParserCreator parserCreator = new XmlParserCreator() {
#Override
public XmlPullParser createParser() {
try {
return XmlPullParserFactory.newInstance().newPullParser();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
GsonXml gsonXml = new GsonXmlBuilder().setXmlParserCreator(parserCreator).create();
Channel channel = gsonXml.fromXml(xml, Channel.class);
Log.v("temp", "Title : " + channel.item.title);
}

android parsing xml content from String

Following is the xml content which i get after decrypting an encrypted value
<card order_no="1" id="cmpe0rhm3ym5ha8wlqp4jt7u" place="HOME">33</card>
Now i have the above content in a String called message.
Now i want parse the values such as id and place using the main tag "card" and the number
"33" also to be parsed.
Following is what i have been tried
InputStream inputStream = new ByteArrayInputStream(message.getBytes());
XmlPullParser cardParser = Xml.newPullParser();
cardParser.setInput(inputStream, null);
Map<String, String> attrs = XMLParsers.getAttributes(cardParser);
String cardTag = cardParser.getName();
if (cardTag.equalsIgnoreCase("card"))
{
CardTag card = new CardTag();
card.setId(attrs.get("id"));
card.setPlace(attrs.get("place"));
card.setCardNumericValue(cardParser.getText());
return card;
}
I have stored the string in an InputStream and again tried to parse it, but i am getting a null pointer exception
Value of String cardTag seems to be null when i printed it.
NullPointerException rises at if condition "if (cardTag.equalsIgnoreCase("card"))"
How to do this
The documentation says
For START_TAG or END_TAG events, the (local) name of the current
element is returned when namespaces are enabled. When namespace
processing is disabled, the raw name is returned. For ENTITY_REF
events, the entity name is returned. If the current event is not
START_TAG, END_TAG, or ENTITY_REF, null is returned.
So, I believe you current event is START_DOCUMENT and you need call cardParser.next() to get next start tag event. Please take a look on example
public class SimpleXmlPullApp{
public static void main (String args[])
throws XmlPullParserException, IOException
{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) );
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_DOCUMENT) {
System.out.println("Start document");
} else if(eventType == XmlPullParser.START_TAG) {
System.out.println("Start tag "+xpp.getName());
} else if(eventType == XmlPullParser.END_TAG) {
System.out.println("End tag "+xpp.getName());
} else if(eventType == XmlPullParser.TEXT) {
System.out.println("Text "+xpp.getText());
}
eventType = xpp.next();
}
System.out.println("End document");
}
}
output
Start document
Start tag foo
Text Hello World!
End tag foo
End document

How to parse properties of a tag value in xml file in Android

I'm developing a weather application. The Xml file is successfully parsed. But I want to read this value.
<yweather:astronomy sunrise="6:03 am" sunset="6:17 pm"/>
But when I get astronomy to a text feild, it returns null. But In logcat it is shows that astronomy tag has been passed.
I want to get the values of sunrise and sunset. Please help me with this. Thanks in advance
XmlHelper.java
#Override
public void endElement(String uri, String localName, String qName) throws SAXException
{
currTag = false;
if(localName.equalsIgnoreCase("pubDate")) post.setDescription(currTagVal);
else if(localName.equalsIgnoreCase("lastBuildDate")) post.setLastBuildDate(currTagVal);
else if(localName.equalsIgnoreCase("yweather:location city")) post.setLocation(currTagVal);
else if(localName.equalsIgnoreCase("channel")) Yweather.add(post);
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
Log.i(TAG, "TAG: " + localName);
currTag = true; currTagVal = ""; // Whenever <post> element is encountered it will create new object of PostValue
if(localName.equals("channel"))
{
post = new WeatherValues();
}
}
MainActivity.java
#Override
protected void onPostExecute(Void result)
{
StringBuilder builder = new StringBuilder();
for(WeatherValues post : helper.Yweather) {
builder.append(post.getLocation());
}
tvResponse.setText(builder.toString());
pd.dismiss();
}
}
This is the xml file
http://weather.yahooapis.com/forecastrss?w=2189713
I think your problem is caused because the xml file is using namespaces. And you can not read from yweather namespace.
For this I would use XmlPullParser (I like it the most)
first you muse specify Feature and set an InputStream from which you will read the xml file.
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(Inputstream_from_which_you_read, null);
Then you need to parse the entire document something like:
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_TAG && parser.getName().equals("astronomy"){
// yweather:forecast - forecast is name of the element, yweather is namespace
String attribute = parser.getAttributealue("yweather","sunrise"); // where you specify the namespace and attribute name
}
eventType = parser.next();
}
You are trying to read values from tag.
According to my knowledge SAXParser reads the Whole tag and returns value between these tags because i have already done this and now m trying to place data after a specific tag in XML file but fail every time help me if you can.
<Placemark id="2">
<styleUrl>#icon-503-DB4436</styleUrl>
<name>Point 2</name>
<ExtendedData>
</ExtendedData>
<description><![CDATA[jc]]></description>
<Point>
<coordinates>73.07473,33.668113,0.0</coordinates>
</Point>
</Placemark>
bcause start element search (you can specify your own) and end element search all the tags between tags untill <\Placemark> is not found.... you can skip any tag according to your requirment
OR Try this may it help you
String filepath = "c:\\file.xml";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filepath);
Node placemark = doc.getElementsByTagName("Placemark").item(0);
NamedNodeMap attr = Placemark.getAttributes();
Node nodeAttr = attr.getNamedItem("id");

XML object storage

I've created an XML pull-parser which pulls details of an xml out:
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new InputStreamReader(response3.getEntity().getContent()));
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_DOCUMENT) {
System.out.println("Start document");
} else if(eventType == XmlPullParser.START_TAG) {
System.out.println("Start tag "+xpp.getName());
} else if(eventType == XmlPullParser.END_TAG) {
System.out.println("End tag "+xpp.getName());
} else if(eventType == XmlPullParser.TEXT) {
System.out.println("Text "+xpp.getText());
}
eventType = xpp.next();
}
This searches through the XML correctly pulling out different tags etc.
My problem is now that I wish to store these. The basic structure is that it stores a series of cards, each with an attribute list. The outer tag would be something like <card> and inside there would be many attributes such as <resourceid>, <price> etc.
I wish to store each card in an easy to retrieve manner. I was thinking of using SQlite but have very little experience with it.Is it possible to do this as the parser steps through?
Added my class here
public class SecondActivity {
String resourceid;
String startprice;
String currentbid;
String buynowprice;
String expires;
public String getResourceId(){
return this.resourceid;
}
public String getStartPrice(){
return this.startprice;
}
public String getCurrentBid(){
return this.currentbid;
}
public String getBuyNowPrice(){
return this.buynowprice;
}
public String getExpires(){
return this.expires;
}
public void setResourceId(String resourceidin){
this.resourceid = resourceidin;
}
public void setStartPrice(String startpricein){
this.startprice = startpricein;
}
public void setCurrentBid(String currentbidin){
this.currentbid = currentbidin;
}
public void setBuyNowPrice(String buynowpricein){
this.buynowprice = buynowpricein;
}
public void setExpires(String expiresin){
this.expires = expiresin;
}
}
I now just call each statement i.e. the set inside where the parser finds the tag values, I then call a store, passing it this object? How do I then clear all values inside object?
Thanks for all the help, most appreciated.
Trying to find the start of the card as defined by
added this to my code:
else if(eventType == XmlPullParser.START_TAG) {
if (xpp.getName() == "auctionInfo"){
this.setMyflag(1);
System.out.println("IN THE IF FLAG IS SET TO 1");
}
System.out.println("Start tag "+xpp.getName());
Unfortunately it never enters the if, and I am stumped as to why!
Sure you can. For some input about how to use SQLite in Android, see here.
You could (for example) create a class which holds the informations for one of your <card>-tags (to build something like a data-package for one card) and then perform the Database-Inserts in another method which takes an Object of this class and processes it.
Your <card>-element will have multiple child-elements or attributes. Those are the fields you for your new class. When the parser finds one of those Child-Elements/Attributes, you set the corresponding field in your class.
When the parser finds the next <card>-element, you first call your storeCardInDB()-method (or whatever you call it) and pass it the filled out Object.
The method will take the fields from your Object, bind them to a PreparedStatement (for example) and send it to the Database.
This is done for every <card>-element in your XML-File.
Okay, there is a difference in comparing two ints and two Strings. If you want to know if the content of a String matches the content of another String, you'll need to use the equals()-method:
if ( xpp.getName().equals("auctionInfo") ) {[...]}
Here is a nice article which should clear the background of this behavior.

Categories

Resources