SAX parser get attribute from endelement - java

I use SAX XML Parser and when I use:
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
I can get attributes.
But I need get attributes from public void endElement
To parse something like that:
<item name="test" value="somedata" />
Code:
public class SAXXMLHandler extends DefaultHandler {
private ArrayList<itemsList> items;
private String tempVal;
private itemsList tempEmp;
private PackageManager manager;
private String packName;
public SAXXMLHandler(PackageManager manager, String packName) {
items = new ArrayList<itemsList>();
this.manager = manager;
this.packName = packName;
}
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
Log.d("INFO", "startElement " + localName + ", " + qName + ", " + attributes);
// reset
tempVal = "";
if (qName.equalsIgnoreCase("item")) {
// create a new instance of employee
tempEmp = new itemsList();
tempEmp.setName(attributes.getValue("name"));
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
Log.d("INFO", "endElement " + localName + ", " + qName);
}
And don't logcat from startElement
UPDATE
I use in Fragment:
SAXXMLHandler handler = new SAXXMLHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
saxParser.parse(asset, handler);
items = SAXXMLHandler.icons;
Util.l(String.valueOf(SAXXMLHandler.icons.size())); //log
for(itemList item:SAXXMLHandler.icons)
{
Util.l(item.getComponent()+"\t\t"+item.getComponent()); //log
}
SAXXMLHandler look:
public class SAXXMLHandler extends DefaultHandler {
public static ArrayList<itemsList> items;
private itemsList item;
public SAXXMLHandler() {
items = new ArrayList<itemsList>();
}
public void characters(char[] ch, int start, int length)
throws SAXException {
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
item = new itemsList();
Log.d("INFO", "startElement " + localName + ", " + qName);
if (qName.equalsIgnoreCase("item")) {
item.setComponent(attributes.getValue("component"));
items.add(item);
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
}
}
And still nothing :/
XML file in other app which I parse
http://pastebin.com/5GEthfmU

In the given XML line..
<item name="test" value="somedata" />
name and value are attributes which only can be retrieved in startElement() method. Because, Attributes attributes parameter is only passed into startElement(String uri, String localName, String qName, Attributes attributes) method. If you look at endElement(String uri, String localName, String qName) method there has no Attributes attributes. That's why you can't retrieve any attribute from endElement() method. So, if you want to retrieve any attributes from a XML then you have to retrieve them inside startElement(String uri, String localName, String qName, Attributes attributes) method.

Change System.out.println to ur Log.ins ..
Item .java
package com.rofl;
public class Item {
private String component;
private String drawable;
public String getComponent() {
return component;
}
public void setComponent(String component) {
this.component = component;
}
public String getDrawable() {
return drawable;
}
public void setDrawable(String drawable) {
this.drawable = drawable;
}
}
SAXXMLHandler .java
package com.rofl;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXXMLHandler extends DefaultHandler {
public static void main(String argv[]) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
SAXXMLHandler handler = new SAXXMLHandler();
saxParser.parse("src/file.xml", handler);
System.out.println(SAXXMLHandler.itemList.size());
for(Item item:itemList)
{
System.out.println(item.getComponent()+"\t\t"+item.getDrawable());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<Item> itemList = new ArrayList<Item>();
private Item item;
public SAXXMLHandler() {
itemList = new ArrayList<Item>();
}
public void characters(char[] ch, int start, int length)
throws SAXException {
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
item = new Item();
if (qName.equalsIgnoreCase("item")) {
item.setComponent(attributes.getValue("component"));
item.setDrawable(attributes.getValue("drawable"));
itemList.add(item);
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
}
}
output will be:-
8
ComponentInfo{com.designrifts.ultimatethemeui/ultimatethemeui.themeactivity} icon
ComponentInfo{com.chrislacy.actionlauncher.pro/com.chrislacy.launcher.Launcher} apps_actionlauncherpro
ComponentInfo{com.teslacoilsw.launcher/com.android.launcher2.Launcher} apps_novalauncher
ComponentInfo{com.teslacoilsw.launcher.prime/.NovaLauncherPrimeActivity} apps_novalauncher
ComponentInfo{com.anddoes.launcher/com.anddoes.launcher.Launcher} apps_apexlauncher
ComponentInfo{com.anddoes.launcher.pro/com.anddoes.launcher.pro.ApexLauncherProActivity} apps_apexlauncher
ComponentInfo{org.adw.launcher/org.adw.launcherlib.Launcher} apps_adwlauncher
ComponentInfo{org.adwfreak.launcher/org.adw.launcherlib.Launcher} apps_adwex

Related

Java XML Parsing using SAXParser

I have an API.When we request it will produce XML as response data
The below is the API Response for Description field:
<parameter>
<name>description</name>
<value>Description Description</value>
</parameter>
The below is the code to parse XML File(SAXPraser)
public class WorkOrderDataHandler extends DefaultHandler {
public WorkOrderDataHandler() {
parameterList = new ArrayList<Parameter>();
contentsOfTheCurrentTag = new StringBuilder();
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("Details")) {
ticketData = new TicketInterMediateData();
}
if (qName.equalsIgnoreCase("parameter")) {
parameter = new Parameter();
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
int length = contentsOfTheCurrentTag.length();
if (qName.equalsIgnoreCase("name")) {
parameter.setName(contentsOfTheCurrentTag.toString().trim());
}
if (qName.equalsIgnoreCase("value")) {
parameter.setValue(contentsOfTheCurrentTag.toString().trim());
}
if (qName.equalsIgnoreCase("parameter")) {
parameterList.add(parameter);
}
if (qName.equalsIgnoreCase("parameter")) {
if ("workorderid".equals(parameter.getName())) {
ticketData.setIt360ticketid(Integer.parseInt(parameter
.getValue().trim()));
}
else if ("description".equals(parameter.getName())) {
System.out.println("Handler desc"+ parameter.getValue());//DescriptionDescriptionÂ
ticketData.setDescription((parameter.getValue()));
}
}
contentsOfTheCurrentTag.delete(0, length);
}
public void characters(char ch[], int start, int length)
throws SAXException {
contentsOfTheCurrentTag.append(ch, start, length);
}
}
Output:
When i tried to parse the description field. i am getting the output as DescriptionDescriptionÂ
Could anyone please help

parsing xmll file through java

I am using SAXParse in java to parse an xml file. I was successfully able to do this with one of the files but I moved to second file and tried reading an attribute I kept getting null. I have thought of every possible cause I can but I am not able to figure it out.
Here's a sample of xml file:
<?xml version="1.0" encoding="UTF-8"?>
<ProcessorStatusCode/>
<StatusCode>E</StatusCode>
<ErrorNo>1852</ErrorNo>...
And here's my java code:
public class ReadXML
{
public static void main(String[] args) throws IOException,SAXException, ParserConfigurationeException
{
String OrderNum;
SAXParserFactory parser = SAXParserFactory.newInstance();
SAXParser Sparser = parser.newSAXParser();
ReadXML handler = new ReadXML();
Sparser.parse("ErrorDescription.xml",handler);
}
public void characters(char[] buffer,int start,int length)
{
temp = new String(buffer, start, length);
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
temp = " ";
if(qName.equalsIgnoreCase("ErrorNo"))
{
//transaction = new Transaction();
OrderNum = attributes.getValue(ErrorNo);
}
}
public void endElement(String uri, String localName, String qName) throws SAXException
{
if(qName.equalsIgnoreCase("ErrorNo"))
{
System.out.println(OrderNum);
}
}
}//end of class
String OrderNum is declared as a local variable in the main() method, it should be a class member variable instead to be accessible in ReadXML.startElement().

Sax parser issues in android

I'm trying to parse a xml using SAX parser. The code works fine on pc but on android the elements doesn't get added to list .
In the code i'm trying to add the data within the tags sunrise & sunset onto the list array
In public
void endElement(..) {}
System.out.println("size of list " + timeLst.size()); //Always shows 0 in android
Below is the code..
TimeServiceParser tsp = new TimeServiceParser();
tsp.parseDocument(new URL("http://www.earthtools.org/sun/47.566667/-52.716667/14/3/99/1"));
tsp.printData();
public class TimeService extends DefaultHandler {
public void parseDocument(URL sourceUrl) {
SAXParserFactory spf = SAXParserFactory.newInstance();
try{
SAXParser sp = spf.newSAXParser();
InputStream is = sourceUrl.openStream();
sp.parse(is, this);
}catch(SAXException se) {
...
}
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
tempVal = "";
if(qName.equalsIgnoreCase("sunrise")) {
tempTimeData = new TimeData();
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equalsIgnoreCase("sunrise")) {
tempTimeData.setSunriseTime(tempVal);
timeLst.add(tempTimeData);
}else if(qName.equalsIgnoreCase("sunset")) {
if(tempTimeData!=null) {
TimeData t = (TimeData)(timeLst.get(0));
t.setSunsetTime(tempVal);
}
}
System.out.println("size of list " + timeLst.size()); //Always shows 0 in android
}
public void characters(char[] ch, int start, int length) throws SAXException {
tempVal = new String(ch , start , length);
}
public void printData() {
Iterator<TimeData> it = timeLst.listIterator();
while(it.hasNext()) {
TimeData td = (TimeData)(it.next());
System.out.println(td.getSunriseTime());
System.out.println(td.getSunsetTime());
}
}
}

How to get content of <tagname> that contains other embedded XML tag in Java?

I have an XML document that has HTML tags included:
<chapter>
<h1>title of content</h1>
<p> my paragraph ... </p>
</chapter>
I need to get the content of <chapter> tag and my output will be:
<h1>title of content</h1>
<p> my paragraph ... </p>
My question is similar to this post: How parse XML to get one tag and save another tag inside
But I need to implement it in Java using SAX or DOM or ...?
I found a soluton using SAX in this post: SAX Parser : Retrieving HTML tags from XML but it's very buggy and doesn't work with large amounts of XML data.
Updated:
My SAX implementation:
In some situation it throw exception: java.lang.StringIndexOutOfBoundsException: String index out of range: -4029
public class MyXMLHandler extends DefaultHandler {
private boolean tagFlag = false;
private char[] temp;
String insideTag;
private int startPosition;
private int endPosition;
private String tag;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
tagFlag = true;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
insideTag = new String(temp, startPosition, endPosition - startPosition);
tagFlag = false;
}
}
public void characters(char ch[], int start, int length)
throws SAXException {
temp = ch;
if (tagFlag) {
startPosition = start;
tagFlag = false;
}
endPosition = start + length;
}
public String getInsideTag(String tag) {
this.tag = tag;
return insideTag;
}
}
Update 2: (Using StringBuilder)
I have accumulated characters by StringBuilder in this way:
public class MyXMLHandler extends DefaultHandler {
private boolean tagFlag = false;
private char[] temp;
String insideTag;
private String tag;
private StringBuilder builder;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
builder = new StringBuilder();
tagFlag = true;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
insideTag = builder.toString();
tagFlag = false;
}
}
public void characters(char ch[], int start, int length)
throws SAXException {
if (tagFlag) {
builder.append(ch, start, length);
}
}
public String getInsideTag(String tag) {
this.tag = tag;
return insideTag;
}
}
But builder.append(ch, start, length); doesn't append Start tag like<EmbeddedTag atr="..."> and </EmbeddedTag> in the Buffer. This Code print Output:
title of content
my paragraph ...
Instead of expected output:
<h1>title of content</h1>
<p> my paragraph ... </p>
Update 3:
Finally I have implemented the parser handler:
public class MyXMLHandler extends DefaultHandler {
private boolean tagFlag = false;
private String insideTag;
private String tag;
private StringBuilder builder;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
builder = new StringBuilder();
tagFlag = true;
}
if (tagFlag) {
builder.append("<" + qName);
for (int i = 0; i < attributes.getLength(); i++) {
builder.append(" " + attributes.getLocalName(i) + "=\"" +
attributes.getValue(i) + "\"");
}
builder.append(">");
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (tagFlag) {
builder.append("</" + qName + ">");
}
if (qName.equalsIgnoreCase(tag)) {
insideTag = builder.toString();
tagFlag = false;
}
System.out.println("End Element :" + qName);
}
public void characters(char ch[], int start, int length)
throws SAXException {
temp = ch;
if (tagFlag) {
builder.append(ch, start, length);
}
}
public String getInsideTag(String tag) {
this.tag = tag;
return insideTag;
}
}
The problem with your code is that you try to remember the start and end positions of the string passed to you via the characters method. What you see in the exception thrown is the result of an inside tag that starts near the end of a character buffer and ends near the beginning of the next character buffer.
With sax you need to copy the characters when they are offered or the temporary buffer they occupy might be cleared when you need them.
Your best bet is not to remember the positions in the buffers, but to create a new StringBuilder in startElement and add the characters to that, then get the complete string out the builder in endElement.
Try to use Digester, I've used it years ago, version 1.5 and it were simply to create mapping for xml like you. Just simple article how to use Digester, but it is for version 1.5 and currently there is 3.0 I think last version contains a lot of new features ...

Reading nested tags with sax parser

i am trying to read a xml file with following tag, but the sax parser is unable to read nested tags like
<active-prod-ownership>
<ActiveProdOwnership>
<Product code="3N3" component="TRI_SCORE" orderNumber="1-77305469" />
</ActiveProdOwnership>
</active-prod-ownership>
here is the code i am using
public class LoginConsumerResponseParser extends DefaultHandler {
// ===========================================================
// Fields
// ===========================================================
static String str="default";
private boolean in_errorCode=false;
private boolean in_Ack=false;
private boolean in_activeProdOwnership= false;
private boolean in_consumerId= false;
private boolean in_consumerAccToken=false;
public void startDocument() throws SAXException {
Log.e("i am ","in start document");
}
public void endDocument() throws SAXException {
// Nothing to do
Log.e("doc read", " ends here");
}
/** Gets be called on opening tags like:
* <tag>
* Can provide attribute(s), when xml was like:
* <tag attribute="attributeValue">*/
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
if(localName.equals("ack")){
in_Ack=true;
}
if(localName.equals("error-code")){
in_errorCode=true;
}
if(localName.equals("active-prod-ownership")){
Log.e("in", "active product ownership");
in_activeProdOwnership=true;
}
if(localName.equals("consumer-id")){
in_consumerId= true;
}
if(localName.equals("consumer-access-token"))
{
in_consumerAccToken= true;
}
}
/** Gets be called on closing tags like:
* </tag> */
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if(localName.equals("ack")){
in_Ack=false;
}
if(localName.equals("error-code")){
in_errorCode=false;
}
if(localName.equals("active-prod-ownership")){
in_activeProdOwnership=false;
}
if(localName.equals("consumer-id")){
in_consumerId= false;
}
if(localName.equals("consumer-access-token"))
{
in_consumerAccToken= false;
}
}
/** Gets be called on the following structure:
* <tag>characters</tag> */
public void characters(char ch[], int start, int length) {
if(in_Ack){
str= new String(ch,start,length);
}
if(str.equalsIgnoreCase("success")){
if(in_consumerId){
}
if(in_consumerAccToken){
}
if(in_activeProdOwnership){
str= new String(ch,start,length);
Log.e("active prod",str);
}
}
}
}
but on reaching the tag in_activeProdOwnersip read only "<" as the contents of the tag
please help i need to the whole data to be read
The tags in your XML file and parser does not match. I think you are mixing-up tags with attribute names. Here is the code that correctly parses your sample XML:
public class LoginConsumerResponseParser extends DefaultHandler {
public void startDocument() throws SAXException {
System.out.println("startDocument()");
}
public void endDocument() throws SAXException {
System.out.println("endDocument()");
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes attrs)
throws SAXException {
if (qName.equals("ActiveProdOwnership")) {
inActiveProdOwnership = true;
} else if (qName.equals("Product")) {
if (!inActiveProdOwnership) {
throw new SAXException("Product tag not expected here.");
}
int length = attrs.getLength();
for (int i=0; i<length; i++) {
String name = attrs.getQName(i);
System.out.print(name + ": ");
String value = attrs.getValue(i);
System.out.println(value);
}
}
}
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (localName.equals("ActiveProdOwnership"))
inActiveProdOwnership = false;
}
public void characters(char ch[], int start, int length) {
}
public static void main(String args[]) throws Exception {
String xmlFile = args[0];
File file = new File(xmlFile);
if (file.exists()) {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
DefaultHandler handler = new Test();
parser.parse(xmlFile, handler);
}
else {
System.out.println("File not found!");
}
}
private boolean inActiveProdOwnership = false;
}
A sample run will produce the following output:
startDocument()
code: 3N3
component: TRI_SCORE
orderNumber: 1-77305469
endDocument()
I suspect this is what's going wrong:
new String(ch,start,length);
Here, you're passing a char[] to the String constructor, but the constructor is supposed to take a byte[]. The end result is you get a mangled String.
I suggest instead that you make the str field a StringBuilder, not a String, and then use this:
builder.append(ch,start,length);
You then need to clear the StringBuilder each time startElement() is called.

Categories