I saw an example in mykong - http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/
I tried to make it work for the xml file (below) by making the following modifications to the code in the above page -
1 - Have only two if blocks in startElement() and characters() methods.
2 - Change the print statements in above methods, ie
FIRSTNAME and First Name = passenger id
LASTNAME and Last Name = name
The problem is - In the output, I see the word passenger instead of the value of passenger id. How do i fix that ?
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:android="www.google.com">
<passenger id="001">
<name>Tom Cruise</name>
</passenger>
<passenger id="002">
<name>Tom Hanks</name>
</passenger>
</root>
Java Code
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 ReadXMLFileSAX{
public static void main(String argv[]) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean bfname = false;
boolean blname = false;
public void startElement(String uri, String localName,String qName,
Attributes attributes) throws SAXException {
System.out.println("Start Element :" + qName);
if (qName.equalsIgnoreCase("passenger id")) {
bfname = true;
}
if (qName.equalsIgnoreCase("name")) {
blname = true;
}
}
public void endElement(String uri, String localName,
String qName) throws SAXException {
System.out.println("End Element :" + qName);
}
public void characters(char ch[], int start, int length) throws SAXException {
if (bfname) {
System.out.println("passenger id : " + new String(ch, start, length));
bfname = false;
}
if (blname) {
System.out.println("name : " + new String(ch, start, length));
blname = false;
}
}
};
saxParser.parse("c:\\flight.xml", handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the startElement, when it's for "passenger", Attributes argument you get will have that value.
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("passenger") && attributes != null){
System.out.println(attributes.getValue("id"));
}
}
Related
I'm currently trying to make a java file that can do an export with xml. The only thing I need to actually retrieve is the staff id's and nothing else.If my xml file looks like this:
<? xml version= "1.0" ?>
< company>
< staff id = "22" >
< firstname> kate </firstname >
< lastname> kim </lastname >
< nickname> lolo </nickname >
< salary> 10560</ salary >
</ staff>
< staff>
< firstname> Chelsea </firstname >
< lastname> young</ lastname >
< nickname> cheloung </nickname >
< salary> 200700</ salary >
</ staff>
< staff id = "23" >
< firstname> Dani </firstname >
< lastname> Heil </lastname >
< nickname> Heily </nickname >
< salary> 300000</ salary >
</ staff>
</ company>
and my java code looks like this:
package xmlfunctions;
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 saxParser {
public static void main(String argv[]) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean bfname = false;
public void startElement(String uri, String localName,String qName,
Attributes attributes) throws SAXException {
System.out.println("Start Element :" + qName);
if (qName.equalsIgnoreCase("FIRSTNAME")) {
bfname = true;
}
}
public void endElement(String uri, String localName,
String qName) throws SAXException {
System.out.println("End Element :" + qName);
}
public void characters(char ch[], int start, int length) throws SAXException {
if (bfname) {
System.out.println("First Name : " + new String(ch, start, length));
bfname = false;
}
}
};
saxParser.parse("KatesFile.xml", handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
How can I change it to get it to display the staff id only? That is all I really want not the other tags. Can anyone help please? I'm very unsure as to how to get the id's on their own.
You can get the value of id in startElement(), using the parameter attributes.
public void startElement(String uri, String localName,String qName,Attributes attributes) throws SAXException {
if (qName.equals("staff")) {
System.out.println(attributes.getValue("id"));
}
}
If there is no id in <staff>, the value is null.
i need to read this xml file using sax parser , but the problem is beacuse of the same child node name in different nodes. This is the file:
<MasterData>
<node1>200000</node1>
<Location>
<oa:Code>88</oa:Code>
<oa:Description languageID="en-us">addres1</oa:Description>
<oa:Description languageID="ar-ae">addres2</oa:Description>
</Location>
<address>
<oa:Code>55</oa:Code>
<oa:Description languageID="en-us">Loc1</oa:Description>
<oa:Description languageID="ar-ae">Loc2</oa:Description>
</address>
</MasterData>
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyHandler2 extends DefaultHandler {
private MasterData masterdata= null;
private IssueAuthority issueAuth = null ;
private List<IssueAuthority> issueAuthList = null ;
public MasterData getMasterData() {
return masterdata;
}
boolean bmaster = false ;
boolean bLiceNum = false;
boolean bissueAuth = false ;
boolean bautCode = false ;
boolean bautDescAr = false ;
boolean bautDescEn = false ;
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("MasterData")) {
//initialize Employee object and set id attribute
masterdata = new MasterData();
System.out.println("MasterData");
}else if (qName.equalsIgnoreCase("LicenseNumber")) {
bLiceNum = true;
System.out.println("qName"+qName);
}else if (qName.equalsIgnoreCase("IssueAuthority")) {
bissueAuth = true;
}else if (qName.equalsIgnoreCase("oa:Code")) {
bautCode = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("IssueAuthority")) {
issueAuthList = new ArrayList<IssueAuthority>() ;
issueAuthList.add(issueAuth) ;
}
if (qName.equalsIgnoreCase("MasterData")) {
//add Employee object to list
masterdata.setIssueAuthority(issueAuthList);
}
}
#Override
public void characters(char ch[], int start, int length) throws SAXException {
if (bLiceNum) {
masterdata.setLicenseNumber(new String(ch, start, length));
bLiceNum = false;
} else if (bissueAuth) {
issueAuth = new IssueAuthority();
bissueAuth = false ;
}else if(bautCode){
issueAuth.setCode(Integer.parseInt(new String(ch, start, length)));
bautCode = false ;
}
}
}
this my handler class
You can differentiate between the location & adress Description child nodes by flagging the entry & exit on the parent. Like that you know exactly in which element you child list you are when accessing the text on the child nodes.
The code snippet below illustrates this:
List<String> locationDescriptions = new ArrayList<String>();
List<String> addressDescriptions = new ArrayList<String>();
boolean insideAddress = false ;
boolean insideLocation = false ;
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
...
if (qName.equalsIgnoreCase("Location")) {
insideLocation = true;
}
if (qName.equalsIgnoreCase("address")) {
insideAddress = true;
}
...
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
...
if (qName.equalsIgnoreCase("Location")) {
insideLocation = false;
}
if (qName.equalsIgnoreCase("address")) {
insideAddress = false;
}
...
}
#Override
public void characters(char ch[], int start, int length) throws SAXException {
..
if (insideLocation && (bautDescAr || bautDescEn) {
locationDescriptions.add(new String(ch, start, length));
}
if (insideAddress && (bautDescAr || bautDescEn) {
addressDescriptions.add(new String(ch, start, length));
}
...
}
I have implemented in my app reading a XML. It works fine. But I want to format the text. I've tried in the XML:
<monumento>
<horarios><b>L-V:</b> 10 a 20<br/>S-D: 11 a 15</horarios>
<tarifas>4000</tarifas>
</monumento>
But the only thing I get if I put HTML character is that the text does not display in my app.
I'll have many xml so that I will not always know where to place <b>, <br/>...
How I can do?
Main
StringBuilder builder = new StringBuilder();
for (HorariosTarifasObj post : helper.posts) {
builder.append(post.getHorarios());
}
horario2.setText(builder.toString());
builder = new StringBuilder();
for (HorariosTarifasObj post : helper.posts) {
builder.append(post.getTarifas());
}
tarifa2.setText(builder.toString());
XMLReader
public void get() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
reader.setContentHandler(this);
InputStream inputStream = new URL(URL + monumento + ".xml").openStream();
reader.parse(new InputSource(inputStream));
} catch (Exception e) {
}
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currTag = true;
currTagVal = "";
if (localName.equals("monumento")) {
post = new HorariosTarifasObj();
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
currTag = false;
if(localName.equalsIgnoreCase("horarios")) {
post.setHorarios(currTagVal);
} else if(localName.equalsIgnoreCase("tarifas")) {
post.setTarifas(currTagVal);
} else if (localName.equalsIgnoreCase("monumento")) {
posts.add(post);
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (currTag) {
currTagVal = currTagVal + new String(ch, start, length);
currTag = false;
}
}
Try CDATA:
<monumento>
<horarios><![CDATA[<b>L-V:</b> 10 a 20<br/>S-D: 11 a 15]]></horarios>
<tarifas>4000</tarifas>
</monumento>
In XML, < and > characters are reserved for XML tags. You will need to protect them by replacing them with special encoding characters.
You can use > for > and < for <
(edit) Eomm answer is right, CDATA does this as well, and more simple
Also, to use HTML coding in TextView, you will need to use Html.fromHtml() method
For instance :
tarifa2.setText(Html.fromHtml(builder.toString()));
I am trying to parse the description tag in the xml but it only outputs one line:
description: <img src=http://www.ovations365.com/sites/ovations365.com/images/event/441705771/sparkswebsite_medium.jpg alt="SPARKS: Understanding Energy">
That is only a small part of the text in the CDATA and I'm trying to output the description for multiple items. Why can't I get the whole CDATA?
The XML is located: http://feeds.feedburner.com/Events-Ovations365
package com.example.ovations_proj;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.example.ovations_proj.RssItem;
public class RssParseHandler extends DefaultHandler {
private List<RssItem> rssItems;
// Used to reference item while parsing
private RssItem currentItem;
// Parsing title indicator
private boolean parsingTitle;
// Parsing link indicator
private boolean parsingLink;
private boolean parsingDes;
public RssParseHandler() {
rssItems = new ArrayList<RssItem>();
}
public List<RssItem> getItems() {
return rssItems;
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("Start Element :" + qName);
if ("item".equals(qName)) { //item
currentItem = new RssItem();
} else if ("title".equals(qName)) { //title
parsingTitle = true;
} else if ("link".equals(qName)) { //link
parsingLink = true;
}else if ("description".equals(qName) ) { //description
parsingDes = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("End Element :" + qName);
if ("item".equals(qName)) {
rssItems.add(currentItem);//item
currentItem = null;
} else if ("title".equals(qName)) {//title
parsingTitle = false;
} else if ("link".equals(qName)) {//link
parsingLink = false;
} else if ("description".equals(qName) ) { //description
parsingDes = false;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (parsingTitle) {
if (currentItem != null){
currentItem.setTitle(new String(ch, start, length));
}
} else if (parsingLink) {
if (currentItem != null) {
currentItem.setLink(new String(ch, start, length));
parsingLink = false;
}
} else if (parsingDes) {
if (currentItem != null) {
currentItem.setDes(new String(ch, start, length));
System.out.println("description: " + currentItem.getDes());
parsingDes = false;
}
}
}
}
It seems that the character data in the <![CDATA[...]]> sections is being sent in multiple chunks, i.e. in multiple calls to the characters method.
The ContentHandler documentation for the characters method mentions that SAX parsers are free to do this:
SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks[....]
You'll therefore need to adjust your characters method to handle being called multiple times for the same chunk of contiguous character data.
When i try to read the xml from java using SAX parser, it is unable to read the content in element present after special character
For ex:
<title>It's too difficult</title>
After reading using the SAX parser, it's displaying only It
How to handle special characters. My sample code is as below
package com.test.java;
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 ReadXMLUsingSAXParser {
public static void main(String argv[]) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
int titleCount;
boolean title = false;
boolean description = false;
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
// System.out.println("Start Element :" + qName);
if (qName.equalsIgnoreCase("title")) {
title = true;
titleCount+=1;
}
if (qName.equalsIgnoreCase("description")) {
description = true;
}
}
public void endElement(String uri, String localName,
String qName)
throws SAXException {
// System.out.println("End Element :" + qName);
}
public void characters(char ch[], int start, int length)
throws SAXException {
if (title&&titleCount>2) {
System.out.println("title : "
+ new String(ch, start, length)+":"+titleCount);
title = false;
}
if (description) {
System.out.println("description : "
+ new String(ch, start, length));
description = false;
}
}
};
saxParser.parse("C:\\Documents and Settings\\sukumar\\Desktop\\sample.xml", handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The characters(char ch[], int start, int length) methode does not read full lines, you should store the characters in a StringBuffer and use it in the endElemen method.
E.g.:
private StringBuffer buffer = new StringBuffer();
public void endElement(String uri, String localName,
String qName)
throws SAXException {
if (qName.equalsIgnoreCase("title")) {
System.out.println("title: " + buffer);
}else if (qName.equalsIgnoreCase("description")) {
System.out.println("description: " + buffer);
}
buffer = new StringBuffer();
}
public void characters(char ch[], int start, int length)
throws SAXException {
buffer.append(new String(ch, start, length));
}