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.
Related
i can't access the inner tag to get the image "url"
here my tag name is "enclosure" and it contain another one called "url" and this is what i want to get...
here the a whole class i created
**public class ParseApplications {
private static final String TAG = "ParseApplications";
private ArrayList<NewsFeeds> application;
public ParseApplications() {
this.application = new ArrayList<>();
}
public ArrayList<NewsFeeds> getApplication() {
return application;
}
public boolean Parse(String xmlData) {
boolean status = true;
NewsFeeds currentNews = null;
boolean InEntry = false;
String textValue = "";
boolean gotImage = false;
try {
// XmlPullParserFactory This class is used to create implementations of XML Pull Parser defined in XMPULL
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//coming line mean that the xml parse i will handle it by my code
/*
Specifies that the parser produced by this factory will provide support for XML namespaces.
By default the value of this is set to false.
Parameters
awareness
boolean: true if the parser produced by this code will provide support for XML namespaces; false otherwise.
*/
factory.setNamespaceAware(true);
//XML Pull Parser is an interface that defines parsing functionality provided in XMLPULL V1 API
//newPullParser is Creates a new instance of a XML Pull Parser using the currently configured factory features.
XmlPullParser xxp = factory.newPullParser();
xxp.setInput(new StringReader(xmlData));
//getEventType Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.). return int
int eventType = xxp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName = xxp.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
Log.d(TAG, "Parse: Starting tag for " + tagName);
if ("item".equalsIgnoreCase(tagName)) {
InEntry = true;
currentNews = new NewsFeeds();
}
break;
case XmlPullParser.TEXT:
textValue = xxp.getText();
break;
case XmlPullParser.END_TAG:
if (InEntry) {
if ("item".equalsIgnoreCase(tagName)) {
application.add(currentNews);
} else if ("title".equalsIgnoreCase(tagName)) {
currentNews.setName(textValue);
} else if ("pubdate".equalsIgnoreCase(tagName)) {
currentNews.setTheDate(textValue);
} else if ("description".equalsIgnoreCase(tagName)) {
currentNews.setSummry(textValue);
} else if ("link".equalsIgnoreCase(tagName)) {
currentNews.setTitle(textValue);
} else if ("enclosure".equalsIgnoreCase(tagName)) {
currentNews.setImageUrl(textValue);
}
}
break;
default:
//nothing to do
}
eventType = xxp.next();
}
for (NewsFeeds app : application) {
Log.d(TAG, "*********************");
Log.d(TAG, app.toString());
}
} catch (Exception e) {
status = false;
}
return status;
}
}**
i can't access the inner tag to get the image "url" here my tag name is "enclosure" and it contain another one called "url" and this is what i want to get... here the a whole class i created
I suggest printing the raw data and see the hierarchy of the tags. just do a Log without parsing the data and read it yourself. It might be missing or you need to access a parent tag before you get it.
also this might seem basic but are you sure you typed it correctly ? (capital letters, spaces etc)
How about the other tags ? I guess you are getting them correctly .
SOLVED
JUST TWO LINES
else if ("enclosure".equalsIgnoreCase(tagName)) {
String url = xxp.getAttributeValue(0);
currentNews.setImageUrl(url);
}
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
I know that via the Account Manager I can access to the list of the accounts on the device.
Account[] accounts = AccountManager.get(this).getAccounts();
I know as well that using the android.settings.ACCOUNT_SYNC_SETTINGS I can open the Sync Settings for a specific account
Intent in=new Intent("android.settings.ACCOUNT_SYNC_SETTINGS");
in.putExtra("account", accounts[3]);
What I would like to do is to open the "Account Settings" for a specific account, like this:
And not like this:
General Approach:
The tricky part is that Android's definition of Account is pretty abstract, so depending on your use case you'll encounter accounts without these screens, or with multiple screens. These screens may not look like Preferences/Settings screens at all - they could be any Activity as defined by the Account authenticator.
Generally though, I think this is what you could do:
Use the getAuthenticatorTypes() method of AccountManager. This
will give you all of the AuthenticatorDescriptions. Depending on
your use case, you can pick the AuthenticatorDescription you care
about (based on the "type" value) and just further investigate that.
http://developer.android.com/reference/android/accounts/AccountManager.html#getAuthenticatorTypes()
The AuthenticatorDescription will tell you the
accountPreferencesId that defines the "hierarchy of
PreferenceScreen to be added to the settings page for the account".
Which in turn defines a "PreferenceScreen xml hierarchy that
contains a list of PreferenceScreens that can be invoked to manage
the authenticator".
http://developer.android.com/reference/android/accounts/AuthenticatorDescription.html
Use the accountPreferencesId and the package provided by the
AuthenticatorDescription to parse the Intents you need, allowing you
to navigate your user to them. Reference for what the XML will look
like:
http://developer.android.com/reference/android/accounts/AbstractAccountAuthenticator.html
tl;dr - the code:
Here's a method that finds the Activity action/class and starts it. It doesn't account for the fact that there may be multiple Activities defined in the Preferences XML referenced above. In fact, it doesn't account for a lot of error scenarios and can surely be optimized, but should serve as a decent proof of concept and starting point:
//somewhere in your app call this
//com.android.email works to open the email preferences on my Galaxy s4
startPreferenceActivity("com.android.email");
private void startPreferenceActivity(String type) {
AccountManager accountManager = AccountManager.get(this);
AuthenticatorDescription[] descriptions = accountManager.getAuthenticatorTypes();
AuthenticatorDescription neededDescription = null;
for (AuthenticatorDescription description : descriptions) {
if (description.type.contains(type)) {
neededDescription = description;
break;
}
}
if (neededDescription != null) {
String packageName = neededDescription.packageName;
int prefsId = neededDescription.accountPreferencesId;
try {
Resources resources = getPackageManager().getResourcesForApplication(packageName);
XmlResourceParser xpp = resources.getLayout(prefsId);
xpp.next();
String action = null;
String targetPackage = packageName; //default to the account pref package name...?
String targetClass = null;
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equals("intent")) {
int count = xpp.getAttributeCount();
for (int i = 0; i < count; i++) {
String name = xpp.getAttributeName(i);
if (name.equals("action")) {
action = xpp.getAttributeValue(i);
} else if (name.equals("targetPackage")) {
targetPackage = xpp.getAttributeValue(i);
} else if (name.equals("targetClass")) {
targetClass = xpp.getAttributeValue(i);
}
}
}
}
eventType = xpp.next();
}
if (action != null) {
startActivity(new Intent(action));
} else if (targetClass != null) {
startActivity(new Intent(createPackageContext(targetPackage, Context.CONTEXT_IGNORE_SECURITY), Class.forName(targetClass)));
}
} catch (PackageManager.NameNotFoundException e) {
} catch (Exception e) {
}
}
}
You may have database of your accounts info u can open it and design a similar style form for it this can solve your problem
I have a XML like this:
<node_a>
<node_b>
<required/>
<random_node1/>
</node_b>
<node_c>
<required/>
</node_c>
<node_d>
<random_node2/>
</node_d>
</node_a>
and trying to parse it using XMLPullParser
I want to iterate through the XML and add all the node names that have the child . In this example i my result list should have node_b and node_c.
The problem i face is if i do a parser.next() then the pointer moves ahead and it is impossible for me get back and iterate through them again. There is no api to check for all child nodes.
What will be the best approach to go with.
Something like this?
XmlPullParser paser = Xml.newPullParser();
... other init that you might need ...
parser.next(); // get first token
// In general, you'll need to add error checking such as this:
if (parser.getEventType() != XmlPullParser.START_TAG)
...error...
String parentName = parser.getName(); // this will be "node_a"
parser.next(); // done with first token; fetch next
while (parser.getEventType() == XmlPullParser.START_TAG)
{
String childName = parser.getName(); // will be "node_b" first time through loop
// get nested attributes - e.g. "required"
parser.next();
while (parser.getEventType() == XmlPullParser.START_TAG)
{
String nestedAttribute = parser.getName();
... do something with nestedAttribute ...
parser.next();
}
if (parser.getEventType() != XmlPullParser.END_TAG)
...error...
parser.next(); // consume END_TAG for nested attributes
}
if (parser.getEventType() != XmlPullParser.END_TAG)
...error...
// make sure we're at end of file
parser.next(); // consume END_TAG for node_a
if (parser.getEventType() != XmlPullPaarser.END_DOCUMENT)
...error...
I'm new to Android development, and I've been playing around with it a bit. I was trying to create a program that has a small database-like collection of never-changing data. In C#, my currently best language, I'd use a List of a custom class and serialize that to an xml file, then read that into my application at runtime. I found the /xml resource folder in Android, but I'm not sure how I would go about doing what I'm envisioning. What would be the best way to go about doing this?
The data will never need to change. Example:
Blob | A | B
----------------
Blob 1 | 23 | 42
Blob 2 | 34 | 21
I know that's laid out like a table, but using a database doesn't really make sense to me because the data will never change, and I would need a way to store it to initially populate the database anyway.
So basically I'm looking for a way to store somewhat-complex static data in my application. Any ideas?
EDIT: I also saw the /raw folder. So I could store things in /res/raw or /res/xml. But I'm not sure what would be the best way to store/parse the data...
I think this is the BEST solution and i am already using this one to store Static-data in my every project.
For that...
You can do one thing, make one xml file namely "temp.xml" ..and store the data in temp.xml as follows:
<?xml version="1.0" encoding="utf-8"?>
<rootelement1>
<subelement> Blob 1
<subsubelement> 23 </subsubelement>
<subsubelement> 42 </subsubelement>
</subelement>
<subelement>Blob 2
<subsubelement> 34 </subsubelement>
<subsubelement> 21 </subsubelement>
</subelement>
</rootelement1>
and then use XML PullParser technique to parse data.
You can have coding samples of PullParsing technique on Example , refer this example for better idea.
Enjoy!!
The best way is to use the Android Resource Heirarchy.
In the res/values/ directory, you can store any number of key-value pairs for several basic data types. In your app, you would refer to them using an autogenerated resource id (name based on your resource's key). See the link above for more documentation and details.
Android also supports raw datafiles. You could store your data in the file directory under res/raw/yourfile.dat
You you create your data in whatever text based format you want and then read it on activity startup using the resource access apis.
I have used Simple for xml parsing in the past. I think it has the least amount of code if you know what to expect in xml, which in your case you do.
http://simple.sourceforge.net/
According to the doc, /xml is the way to go.
Providing Resources
xml/ Arbitrary XML files that can be read at run-time by calling
Resources.getXML().
Various XML configuration files must be saved here, such as a searchable configuration.
Documentation for getXML()
I also made a working example:
the XML structure:
<?xml version="1.0" encoding="utf-8"?>
<quizquestions>
<quizquestion>
<header_image_src>ic_help_black_24dp</header_image_src>
<question>What is the Capital of U.S.A.?</question>
<input_type>Radio</input_type>
<answer correct="false">New York City</answer>
<answer correct="true">Washington D.C.</answer>
<answer correct="false">Chicago</answer>
<answer correct="false">Philadelphia</answer>
</quizquestion>
<quizquestion>
<header_image_src>ic_help_black_24dp</header_image_src>
<question>What is the family name of the famous dutch painter Vincent Willem van .... ?</question>
<input_type>EditText</input_type>
<answer correct="true">Gogh</answer>
</quizquestion>
</quizquestions>
the Java class to hold parsed data:
public class QuizQuestion {
private int headerImageResId;
private String question;
private String inputType;
private ArrayList<String> answers;
private ArrayList<Boolean> answerIsCorrect;
private ArrayList<Integer> correctAnswerIndexes;
/**
* constructor for QuizQuestion object
*/
QuizQuestion() {
headerImageResId = 0;
question = null;
inputType = null;
answers = new ArrayList<>();
answerIsCorrect = new ArrayList<>();
correctAnswerIndexes = new ArrayList<>();
}
public void setHeaderImageResId(int headerImageResId) {
this.headerImageResId = headerImageResId;
}
public int getHeaderImageResId() {
return headerImageResId;
}
void setQuestion(String question) {
this.question = question;
}
public String getQuestion() {
return question;
}
void setInputType(String inputType) {
this.inputType = inputType;
}
public String getInputType() {
return inputType;
}
void addAnswer(String answer, boolean isCorrect)
{
if (isCorrect)
correctAnswerIndexes.add(answers.size());
answers.add(answer);
answerIsCorrect.add(isCorrect);
}
public ArrayList<String> getAnswers() {
return answers;
}
public String getAnswer(int index)
{
// check index to avoid out of bounds exception
if (index < answers.size()) {
return answers.get(index);
}
else
{
return null;
}
}
public int size()
{
return answers.size();
}
}
the parser itself:
/**
* Created by bivanbi on 2017.02.23..
*
* class to parse xml resource containing quiz data into ArrayList of QuizQuestion objects
*
*/
public class QuizXmlParser {
public static String lastErrorMessage = "";
/**
* static method to parse XML data into ArrayList of QuizQuestion objects
* #param activity is the calling activity
* #param xmlResourceId is the resource id of XML resource to be parsed
* #return null if parse error is occurred or ArrayList of objects if successful
* #throws XmlPullParserException
* #throws IOException
*/
public static ArrayList<QuizQuestion> parse(Activity activity, int xmlResourceId)
throws XmlPullParserException, IOException
{
String logTag = QuizXmlParser.class.getSimpleName();
Resources res = activity.getResources();
XmlResourceParser quizDataXmlParser = res.getXml(R.xml.quiz_data);
ArrayList<String> xmlTagStack = new ArrayList<>();
ArrayList<QuizQuestion> quizQuestions = new ArrayList<>();
QuizQuestion currentQuestion = null;
boolean isCurrentAnswerCorrect = false;
quizDataXmlParser.next();
int eventType = quizDataXmlParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT)
{
// begin document
if(eventType == XmlPullParser.START_DOCUMENT)
{
Log.d(logTag,"Begin Document");
}
// begin tag
else if(eventType == XmlPullParser.START_TAG)
{
String tagName = quizDataXmlParser.getName();
xmlTagStack.add(tagName);
Log.d(logTag,"Begin Tag "+tagName+", depth: "+xmlTagStack.size());
Log.d(logTag,"Tag "+tagName+" has "+quizDataXmlParser.getAttributeCount()+" attribute(s)");
// this is a beginning of a quiz question tag so create a new QuizQuestion object
if (tagName.equals("quizquestion")){
currentQuestion = new QuizQuestion();
}
else if(tagName.equals("answer"))
{
isCurrentAnswerCorrect = quizDataXmlParser.getAttributeBooleanValue(null,"correct",false);
if (isCurrentAnswerCorrect == true) {
Log.d(logTag, "Tag " + tagName + " has attribute correct = true");
}
else
{
Log.d(logTag, "Tag " + tagName + " has attribute correct = false");
}
}
}
// end tag
else if(eventType == XmlPullParser.END_TAG)
{
String tagName = quizDataXmlParser.getName();
if (xmlTagStack.size() < 1)
{
lastErrorMessage = "Error 101: encountered END_TAG "+quizDataXmlParser.getName()+" while TagStack is empty";
Log.e(logTag, lastErrorMessage);
return null;
}
xmlTagStack.remove(xmlTagStack.size()-1);
Log.d(logTag,"End Tag "+quizDataXmlParser.getName()+", depth: "+xmlTagStack.size());
// reached the end of a quizquestion definition, add it to the array
if (tagName.equals("quizquestion")){
if (currentQuestion != null)
quizQuestions.add(currentQuestion);
currentQuestion = null;
}
}
// text between tag begin and end
else if(eventType == XmlPullParser.TEXT)
{
String currentTag = xmlTagStack.get(xmlTagStack.size()-1);
String text = quizDataXmlParser.getText();
Log.d(logTag,"Text: "+text+", current tag: "+currentTag+", depth: "+xmlTagStack.size());
if (currentQuestion == null) {
Log.e(logTag,"currentQuestion is not initialized! text: "+text+", current tag: "+currentTag+", depth: "+xmlTagStack.size());
continue;
}
if (currentTag.equals("header_image_src"))
{
int drawableResourceId = activity.getResources().getIdentifier(text, "drawable", activity.getPackageName());
currentQuestion.setHeaderImageResId(drawableResourceId);
}
else if (currentTag.equals("question"))
{
currentQuestion.setQuestion(text);
}
else if (currentTag.equals("answer"))
{
currentQuestion.addAnswer(text, isCurrentAnswerCorrect);
}
else if (currentTag.equals("input_type"))
{
currentQuestion.setInputType(text);
}
else
{
Log.e(logTag,"Unexpected tag "+currentTag+" with text: "+text+", depth: "+xmlTagStack.size());
}
}
eventType = quizDataXmlParser.next();
}
Log.d(logTag,"End Document");
return quizQuestions;
}
}
and finally, calling the parser:
// read quiz data from xml resource quiz_data
try {
quizQuestions = QuizXmlParser.parse(this,R.xml.quiz_data);
Log.d("Main","QuizQuestions: "+quizQuestions);
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
quizQuestions = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
quizQuestions = null;
}
if (quizQuestions == null)
{
Toast.makeText(this,"1001 Failed to parse Quiz XML, sorry", Toast.LENGTH_LONG).show();
finish();
}