I've done XML parsing via XmlPullParser and it works fine until I add special characters to my xml file such as š,č,ř,ž and so on. It replaces the character with "?" sign. Is there any way how to get rid of that?
Here is my Xml parser class:
public class ClubsXmlPullParser {
static final String CLUB = "club";
static final String NAME = "name";
static final String ABOUT = "about";
static final String STADIUM = "stadium";
static final String LOGO = "logo";
static final String MOREABOUT = "moreAbout";
public static List<LeagueClub> getItemsFromFile(Context ctx) {
List<LeagueClub> clubs;
clubs = new ArrayList<LeagueClub>();
LeagueClub curItem = null;
String curText = "";
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
FileInputStream fis = ctx.openFileInput("clubs.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(CLUB)) {
curItem = new LeagueClub();
}
break;
case XmlPullParser.TEXT:
curText = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase(CLUB)) {
clubs.add(curItem);
} else if (tagname.equalsIgnoreCase(NAME)) {
curItem.setName(curText);
} else if (tagname.equalsIgnoreCase(ABOUT)) {
curItem.setAbout(curText);
} else if (tagname.equalsIgnoreCase(STADIUM)) {
curItem.setStadium(curText);
} else if (tagname.equalsIgnoreCase(LOGO)) {
curItem.setLogo(curText);
} else if (tagname.equalsIgnoreCase(MOREABOUT)) {
curItem.setName(curText);
}
break;
default:
break;
}
eventType = xpp.next();
}
} catch (Exception e) {
e.printStackTrace();
}
return clubs;
}
}
Assuming that you know how to obtain the encoding of the file, you can use the alternative version of setInput - setInput(InputStream inputStream, String inputEncoding)
Related
My XML file is something like this:
<Items>
<Nested_item>
<id>1</id>
<name>nested</name>
<description>
<desc_item>1</desc_item>
<desc_item>2</desc_item>
<desc_item>3</desc_item>
</description>
</Nested_item>
<Nested_item>
<id>2</id>
<name>nested2</name>
<description>
<desc_item>1</desc_item>
<desc_item>2</desc_item>
<desc_item>3</desc_item>
</description>
</Nested_item>
<Nested_item>
<id>3</id>
<name>nested3</name>
<description>
<desc_item>1</desc_item>
<desc_item>2</desc_item>
<desc_item>3</desc_item>
</description>
</Nested_item>
</Items>
and I have class Items with atributes which I've putted into ArrayList, I've managed to parse all atributes except desc_item (which I need as ArrayList for every Item object). How can I tell parser to take only third item, for example, and to get those desc_item values as String?
I found solution to my problem, i have parsed inner data and after that i have parsed particular data:
private ArrayList<Proizvod> parseXML (XmlPullParser parser) throws XmlPullParserException, IOException {
ArrayList<Proizvod> proizvodLista = null;
int eventType = parser.getEventType();
Proizvod proizvod = null;
while(eventType != XmlPullParser.END_DOCUMENT){
String name;
switch (eventType){
case XmlPullParser.START_DOCUMENT:
proizvodLista = new ArrayList<Proizvod>();
break;
case XmlPullParser.START_TAG:
name = parser.getName();
//System.out.println(name);
if(name.equals("Proizvod")){
proizvod = new Proizvod();
proizvod.setId(parser.getAttributeValue(null, "id"));
}else if(proizvod != null){
if(name.equalsIgnoreCase("ime_proizvoda")){
proizvod.setIme_proizvoda(parser.nextText());
}else if(name.equalsIgnoreCase("vrsta_proizvoda")){
proizvod.setVrsta_proizvoda(parser.nextText());
}else if(name.equalsIgnoreCase("merna_jedinica")){
proizvod.setVrsta_proizvoda(parser.nextText());
}else if(name.equalsIgnoreCase("Prodavnice")){
proizvod.setLista_prodavnica(parsing(parser));
}
}
break;
case XmlPullParser.END_TAG:
name = parser.getName();
if(name.equalsIgnoreCase("proizvod")&& proizvod !=null){
proizvodLista.add(proizvod);
}
}
eventType = parser.next();
}
return proizvodLista;
}
private ArrayList<String> parsing (XmlPullParser parser) throws XmlPullParserException, IOException {
String print = null;
int eventType = parser.getEventType();
ArrayList<String> lista = new ArrayList<String>();
while(eventType != XmlPullParser.END_DOCUMENT){
String name = parser.getName();
if(name.equalsIgnoreCase("Prodavnice")){break;}
else{
if(eventType==XmlPullParser.START_TAG){
print = parser.nextText();
lista.add(print);
System.out.println(print);
}
}
eventType = parser.next();
}
return lista;
}
And my XML looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Proizvodi>
<Proizvod id="1">
<ime_proizvoda>Mleko</ime_proizvoda>
<vrsta_proizvoda>mlecni proizvod</vrsta_proizvoda>
<merna_jedinica>litar</merna_jedinica>
<Prodavnice>
<Prodavnica>1</Prodavnica>
<Prodavnica>3</Prodavnica>
<Prodavnica>4</Prodavnica>
</Prodavnice>
</Proizvod>
<Proizvod id="2">
<ime_proizvoda>Hleb</ime_proizvoda>
<vrsta_proizvoda>Pekarski proizvod</vrsta_proizvoda>
<merna_jedinica>gram</merna_jedinica>
<Prodavnice>
<Prodavnica>1</Prodavnica>
<Prodavnica>2</Prodavnica>
<Prodavnica>3</Prodavnica>
</Prodavnice>
</Proizvod>
<Proizvod id="3">
<ime_proizvoda>Suvi vrat</ime_proizvoda>
<vrsta_proizvoda>Mesna preradjevina</vrsta_proizvoda>
<merna_jedinica>gram</merna_jedinica>
<Prodavnice>
<Prodavnica>2</Prodavnica>
<Prodavnica>3</Prodavnica>
<Prodavnica>4</Prodavnica>
</Prodavnice>
</Proizvod>
<Proizvod id="4">
<ime_proizvoda>Pecenica</ime_proizvoda>
<vrsta_proizvoda>Mesna preradjevina</vrsta_proizvoda>
<merna_jedinica>100 grama</merna_jedinica>
<Prodavnice>
<Prodavnica>1</Prodavnica>
<Prodavnica>2</Prodavnica>
<Prodavnica>4</Prodavnica>
</Prodavnice>
</Proizvod>
I am not full aware of XMLParsing so i am beginner in XMLParsing. I am using XMLPull parser.
i wanna to store player one and player two in below xml. How can i identify playertag??
<scores sport="tennis">
<category name="Atp - Doubles: Us Open (Usa), Hard" city="Us Open" id="11987">
<match date="08.09.2016" time="19:00" status="Not Started" id="396388">
<player name="Herbert/ Mahut" s1="" s2="" s3="" s4="" s5="" totalscore="" id="22079"/>
<player name="Murray/ Soares" s1="" s2="" s3="" s4="" s5="" totalscore="" id="33098"/>
</match>
<match date="08.09.2016" time="20:30" status="Not Started" id="396400">
<player name="Lopez/ Lopez" s1="" s2="" s3="" s4="" s5="" totalscore="" id="9632"/>
<player name="Carreno-Busta/ Garcia-Lopez" s1="" s2="" s3="" s4="" s5="" totalscore="" id="22770"/>
</match>
</category>
</scores>
Here is my code
public List<LiveScore> parse(InputStream is) {
try {
String tournament = null,tournament_place = null,date = null,time = null,status = null,player_one = null,player_two;
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
parser.setInput(is, null);
liveScoreArrayList = new ArrayList<LiveScore>();
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagname = parser.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if ("category".equals(tagname)){
tournament = parser.getAttributeValue(null,"name");
tournament_place = parser.getAttributeValue(null,"city");
}
if ("match".equals(tagname)){
date = parser.getAttributeValue(null,"date");
time = parser.getAttributeValue(null,"time");
status = parser.getAttributeValue(null,"status");
}
break;
case XmlPullParser.TEXT:
// text = parser.getText();
// Log.i(TAG, "parse: text: "+text);
break;
case XmlPullParser.END_TAG:
if ("player".equals(tagname)){
player_one = parser.getAttributeValue(null,"name");
}
Log.d("LiveMatch", "parse: category : "+tournament+" city = "+tournament_place+" date = "+date+ " time = "+time+" status = "+status+" player_one = "+player_one);
// rankList.add(new Rank(rank,player_name+" \n"+country,points ));
break;
default:
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
return liveScoreArrayList;
}
This is Complete Xml Pull Parsing example.. It may Help you.
https://androidgarden.wordpress.com/2016/09/02/android-xml-pull-parsing-from-sd-card-assets/
I'm trying to make an app for a podcast. My end goal is for a user to be able to click on an episode in a list (which is generated from an RSS feed) and then have the audio play (which is also retrieved from the RSS feed) My problem is with parsing the XML from the RSS feed. I can't seem to figure out how to get the URL out of the enclosure tag for the mp3. Any help would be appreciated. Here is my parsing class
private String data;
private ArrayList<Episodes> mEpisodes;
public ParseEpisodes(String xmlData) {
this.data = xmlData;
mEpisodes = new ArrayList<>();
}
public ArrayList<Episodes> getEpisodes() {
return mEpisodes;
}
public boolean process(){
boolean status = true;
Episodes currentRecord = null;
boolean inEntry = false;
String textValue = "";
String urlValue = "";
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(this.data));
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
String tagName = xpp.getName();
switch(eventType){
case XmlPullParser.START_TAG:
//Log.d("ParseEpisodes", "Starting tag for " + tagName);
if(tagName.equalsIgnoreCase("item")){
inEntry = true;
currentRecord = new Episodes();
}
break;
case XmlPullParser.TEXT:
textValue = xpp.getText();
urlValue = xpp.getText();
break;
case XmlPullParser.END_TAG:
//Log.d("ParseEpisodes", "Ending tag for " + tagName);
if(inEntry){
if(tagName.equalsIgnoreCase("item")){
mEpisodes.add(currentRecord);
inEntry = false;
}else if(tagName.equalsIgnoreCase("title")){
currentRecord.setTitle(textValue);
}else if(tagName.equalsIgnoreCase("enclosure")){
currentRecord.setLink(urlValue);
}
}
break;
}
eventType = xpp.next();
}
}catch (Exception e){
status = false;
e.printStackTrace();
}
return true;
}
here is the xml
<item>
<title>Episode 52 - Facebook Nukes The Show</title>
<link>https://greynoi.se/podcasts/episode-52-facebook-nukes-the-show</link>
<enclosure url="http://greynoi.se/episodes/ep79_m.mp3" length="43312404" type="audio/mpeg"/>
<pubDate>Fri, 15 Jul 2016 15:22:24 -0700</pubDate>
<category>1</category>
<source url="https://greynoi.se">The GR3YNOISE Podcast</source>
<itunes:subtitle>Episode 52 - Facebook Nukes The Show</itunes:subtitle>
<itunes:summary>Episode 52 - Facebook Nukes The Show</itunes:summary>
<content:encoded><![CDATA[Episode 52 - Facebook Nukes The Show"}]]></content:encoded>
<guid>https://greynoi.se/podcasts/episode-52-facebook-nukes-the-show</guid>
</item>
So you want the url after the enclosure url= tag?
If that is the case it is very easy. Just use substrings to find and get the url.
Something like this should work.
int urlTagStart = text.indexOf("<enclosure url="");
int urlTagEnd = text.indexOf(".mp3");
String url = text.substring(urlTagStart + 16, urlTagEnd + 4)
Try this:
...
YOUR CODE
...
while(eventType != XmlPullParser.END_DOCUMENT){
String tagName = xpp.getName();
if (tagName.equalsIgnoreCase("enclosure")) {
int attributeCount = xpp.getAttributeCount();
for(int i = 0; i<attributeCount; i++){
String attrib = xpp.getAttributeName(i);
if(attrib && attrib.equalsIgnoreCase("url")){
String url = xpp.getAttributeValue(i);
}
}
}
if (url != null && !url.isEmpty() && !url.equals("null")) {
Log.d("ParseEpisodes", "URL to mp3: " + url);
}
...
THE REST OF YOUR CODE
...
}
The solution to this ended up being pretty simple. All I needed to do was delete
urlValue = xpp.getText();
from the
case XmlPullParser.TEXT:
Then change
else if(tagName.equalsIgnoreCase("enclosure")){
urlValue = xpp.getAttributeValue(0);
currentRecord.setLink(urlValue);
}
in the
case XmlPullParser.END_TAG:
In one of my projects that i'm working off i'm trying to parse all feeds from an atom xml as this below.
<entry>
<id>tag:blogger.com,1999:blog-4512083858574973357.post-3473864646179740942</id>
<published>2015-09-14T09:28:00.000+03:00</published>
<updated>2015-09-14T15:30:18.832+03:00</updated>
<title type="text">Mytitle</title>
<content>Hello</content>
<author>
<name>Author name</name>
<uri>URI HERE</uri>
<email>EMAIL HERE</email>
<gd:image rel="" width="32" height="32" src="" />
</author>
I can get all tags using the following code but i have no idea how to parse the name of the author.
private Entry readEntry(XmlPullParser parser)
throws XmlPullParserException, IOException, ParseException {
parser.require(XmlPullParser.START_TAG, ns, "entry");
String id = null;
String title = null;
Uri image = null;
String link = null;
String content = null;
String description;
String author = null;
String shortDescription = null;
ArrayList tags= new ArrayList<>();;
long publishedOn = 0;
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
switch (name) {
case "id":
id = readTag(parser, TAG_ID);
break;
case "title":
title = readTag(parser, TAG_TITLE);
break;
case "link":
link = readTag(parser, TAG_LINK);
break;
case "author":
//****************************************************
CANT GET THE NAME OF THE AUTHOR HERE
//****************************************************
break;
case "category": {
String tempLink = readTag(parser, TAGS);
if (tempLink != null) {
tags.add(tempLink);
}
break;
}
case "content": {
String tempLink = readTag(parser, TAG_CONTENT);
if (tempLink != null) {
content = tempLink;
image = Uri.parse(pullImageLink(content));
description = Html.fromHtml(content.replaceAll("<img.+?>", "")).toString().trim();
if (description.length() > 0) {
int descrLength = description.length();
if (descrLength > 250) {
shortDescription = description.substring(0, 250);
} else {
shortDescription = description.substring(0, descrLength);
}
}
}
break;
}
case "published":
publishedOn = getParsedDate(readTag(parser, TAG_PUBLISHED));
break;
default:
skip(parser);
break;
}
}
assert image != null;
return new Entry(id, title, image.toString(), link, content, shortDescription, publishedOn,tags, author);
}
I made a class to parse indoorGML information. The indoorGML has 5 layers.
All the parts work.
In fifth layer, I need to call a tag called posList:
<indoorCore:CellSpace gml:id='L5C1'>
<indoorCore:Geometry2D>
<gml:Polygon >
<gml:exterior>
<gml:LinearRing>
<gml:posList>529.0 840.25 529.0 803.51 540.0 803.51</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</indoorCore:Geometry2D>
<indoorCore:PartialboundedBy>
<indoorCore:CellSpaceBoundary gml:id='L5B1'>
<indoorCore:geometry2D>
<gml:LineString>
<gml:posList>540.0 803.51 529.0 803.51 529.0 840.25</gml:posList>
</gml:LineString>
</indoorCore:geometry2D>
<indoorCore:duality>
<indoorCore:Transition xlink:href='#L5T1'/>
</indoorCore:duality>
</indoorCore:CellSpaceBoundary>
I need the points inside tag posList which are inside the tag polygon. I wrote the parsing like this:
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG:
currentTagName = parser.getName();
if (currentTagName.equals("gml:Polygon")) {
inPolygon = true;
} else if (currentTagName.equals("indoorCore:SpaceLayer")) {
String layer = parser.getAttributeValue(0);
currentLayer = layer;
if (layer.equals("L5")) {
startOfFifthLayer = true;
}
} else if(currentTagName.equals("gml:name")) {
inName = true;
// inNodes=true;
// Log.d("name", "true");
}
if(currentTagName.equals("gml:posList")) {
inLayerFivePolygon = true;
Log.d("Polygon5", "true");
}
break;
case XmlPullParser.END_TAG:
if (currentTagName.equals("indoorCore:SpaceLayer")) {
String layer = parser.getAttributeValue(0);
currentLayer = layer;
currentTagName = parser.getName();
if(currentLayer.equals("L5")) {
endOfFifthLayer = true;
}
}
break;
case XmlPullParser.TEXT:
if (inName) {
// put posList points in an array
String points = parser.getText();
Log.d("PlaceName MapPlace", points);
String[] split = points.split(" ");
inName=false;
} else if(inLayerFivePolygon){
String points = parser.getText();
Log.d("Area MapPlace", points);
String[] split = points.split(" ");
inLayerFivePolygon=false;
}
break;
}
if (endOfFifthLayer) {
break;
}
eventType = parser.next();
}
}
When I just parse tag posList, my program can read the points. But when I want to filter it and put it inside the polygon tag, it does not show the points to me in the Log.
Do you know what is the trick?
thanks a lot!
I solved it by changing the condition of testing the layer in the case XmlPullParser.START_TAG :
else if (currentTagName.equals("indoorCore:SpaceLayer")) {
String layer = parser.getAttributeValue(0);
currentLayer = layer;
if (!layer.equals("L5")) {
inFifthLayer = false;
}else {
inFifthLayer = true;
startOfFifthLayer = true;
}
Then to control the tag, moreover testing the tag, I control the layer again, like this:
if(currentTagName.equals("gml:posList") && inFifthLayer) {
inLayerFivePolygon = true;
Log.d("Polygon5", "true");
}
Finally in the XmlPullParser.TEXT, I parse the points I need like this:
XmlPullParser.TEXT:
if(inLayerFivePolygon){
String points = parser.getText();
String[] split = points.split(" ");
//ArrayList<String> finalPoints = convertToPolygon(points);
// Log.d("Area MapPlace", finalPoints.toString());
Log.d("Area MapPlace2", points);
inLayerFivePolygon=false;
}