Now I use the sax parser to analysis the xml file(the following sample code comes from tutorialspoint). I want to output all the things to a txt file using the BufferedWriter when we call the characters function, while I don't get a way to make this. If I write this BufferedWriter in the characters function, it will only output the last string, since it will only record the last call. If I write this BufferedWriter in the main function, since they are two classes, the UserHandler couldn't recognize the BufferedWriter created in the main function(the dblpSax class). I also tried sth to make a class instance, while I still got involved troubles. Could you give me a way to make this? Thanks.
The Bufferwriter I want to use is as follows:
File writename = new File("output.txt");
writename.createNewFile();
BufferedWriter out = new BufferedWriter(new FileWriter(writename));
public class dblpSax{
public static void main(String[] args){
try {
File inputFile = new File("student.txt");
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
UserHandler userhandler = new UserHandler();
saxParser.parse(inputFile, userhandler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class UserHandler extends DefaultHandler {
boolean bFirstName = false;
boolean bLastName = false;
boolean bNickName = false;
boolean bMarks = false;
public void startElement(String uri,
String localName, String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("student")) {
String rollNo = attributes.getValue("rollno");
System.out.println("Roll No : " + rollNo);
} else if (qName.equalsIgnoreCase("firstname")) {
bFirstName = true;
} else if (qName.equalsIgnoreCase("lastname")) {
bLastName = true;
} else if (qName.equalsIgnoreCase("nickname")) {
bNickName = true;
}
else if (qName.equalsIgnoreCase("marks")) {
bMarks = true;
}
}
public void endElement(String uri,
String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("student")) {
System.out.println("End Element :" + qName);
}
}
public void characters(char ch[],
int start, int length) throws SAXException {
if (bFirstName) {
System.out.println("First Name: "
+ new String(ch, start, length));
bFirstName = false;
} else if (bLastName) {
System.out.println("Last Name: "
+ new String(ch, start, length));
bLastName = false;
} else if (bNickName) {
System.out.println("Nick Name: "
+ new String(ch, start, length));
bNickName = false;
} else if (bMarks) {
System.out.println("Marks: "
+ new String(ch, start, length));
bMarks = false;
}
}
}
You need a BufferedWriter at the same level as the parsing, best customizable outside the DefaultHandler.
try (BufferedWriter out = new BufferedWriter(....)) {
UserHandler userhandler = new UserHandler(out);
saxParser.parse(inputFile, userhandler);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class UserHandler extends DefaultHandler {
private final BufferedWriter out; // Or PrintWriter
UserHandler(BufferedWriter out) {
this.out = out;
}
And then one can all out.write everywhere.
Related
I have more elements on my xml file contains & and others characters html >.
I tested my code but it obtain the first part of my field for example:
SERIES & FILMS
It give only the word SERIES.
And other example:
C>SUDO
It give only C.
My code, my field name is "summary":
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
chars = new StringBuffer();
DefaultHandler handler = new DefaultHandler() {
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
System.out.println("Start Element :" + qName);
if (qName.equals(SUMMARY2)) {
bfSummary = true;
}
if (qName.equals(SERVICE_DATA)) {
idServiceData = attributes.getValue("id");
bfServicedata = true;
}
}
public void endElement(String uri, String localName,
String qName) throws SAXException {
System.out.println("End Element :" + qName + ""
+ mListBaseLineByEpgId.size());
// maliste.put(listeId, summary);
malisteParThem.add(summary);
if (mListBaseLineByEpgId.get(idServiceData) != null) {
List<String> listeModif = mListBaseLineByEpgId
.get(idServiceData);
for (String chaine : malisteParThem) {
listeModif.add(chaine);
}
mListBaseLineByEpgId.replace(idServiceData, listeModif);
} else {
mListBaseLineByEpgId.put(idServiceData, malisteParThem);
}
malisteParThem = new ArrayList<String>();
}
public void characters(char ch[], int start, int length)
throws SAXException {
if (bfSummary) {
summary = new String(ch, start, length);
summary = summary.replace(BEFORETILESUMMARY, "");
// chars.append(summary);
// summary=chars.toString();
summary = removeHtmlFrom(summary);
System.out.println("Summary : " + summary);
bfSummary = false;
}
if (bfServicedata) {
System.out.println("listeId : " + idServiceData);
bfServicedata = false;
}
}
};
File file = new File(cheminFichier);
InputStream inputStream = new FileInputStream(file);
Reader reader = new InputStreamReader(inputStream);
InputSource is = new InputSource(reader);
//is.setEncoding("ISO-8859-1");
saxParser.parse(is, handler);
} catch (Exception e) {
e.printStackTrace();
}
Thank you.
Perhaps this problem is related to the unexpected behavior of SAX parser: it is allowed (per spec) to split the text part of an element and call characters() method multiple times for the same element.
What you need to do is have a StringBuffer or StringBuilder instance variable. You initialize it in startElement(), append to it on characters() and get the full text on endElement()
see this question for more info JAVA SAX parser split calls to characters()
I'm passing in an XML file and a handler to the SAXParser but I'm getting this error:
The attributes for the parse method are defined as (File, DefaultHandler) which match exactly, so I'm not sure where I'm going wrong. Here is the full method:
public String readXML (File readFile) throws Exception {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxFactory.newSAXParser();
final String outputString = "";
DefaultHandler handler = new DefaultHandler() {
boolean bArtist = false;
boolean bAlbumName = false;
boolean bYear = false;
boolean bGenre = false;
public void startElement(String uri, String localName, String qName, Attributes attr)
throws SAXException {
if (qName.equalsIgnoreCase("ARTIST")) { bArtist = true; }
if (qName.equalsIgnoreCase("ALBUMNAME")) { bAlbumName = true; }
if (qName.equalsIgnoreCase("YEAR")) { bYear = true; }
if (qName.equalsIgnoreCase("GENRE")) { bGenre = true; }
}
public void characters(char ch[], int start, int length) {
if (bArtist) {
outputString.concat("Artist: " + new String(ch,start,length) + "\n");
}
if(bAlbumName) {
outputString.concat("Album: " + new String(ch,start,length) + "\n");
}
if(bYear) {
outputString.concat("Year: " + new String(ch,start,length) + "\n");
}
if(bGenre) {
outputString.concat("Genre: " + new String(ch,start,length) + "\n");
}
outputString.concat("\n");
}
};
saxParser.parse(readFile,handler);
return outputString;
}
It should be org.xml.sax.helpers.DefaultHandler
not jdk.internal...
so
import org.xml.sax.helpers.DefaultHandler;
You should probably also define the class that extends the DefaultHandler not just inline it.
I'm trying to get the RSS feed into my android application, I am retrieving feeds like title, description and link of feed but not able to get image for particular feed.
The fallowing is my DefaultXmlHandler class. please go through and help me out.
public class XmlHandler extends DefaultHandler {
private RssFeedStructure feedStr = new RssFeedStructure();
private List<RssFeedStructure> rssList = new ArrayList<RssFeedStructure>();
private int articlesAdded = 0;
// Number of articles to download
private static final int ARTICLES_LIMIT = 15;
StringBuffer chars = new StringBuffer();
public void startElement(String uri, String localName, String qName, Attributes atts) {
chars = new StringBuffer();
if (qName.equalsIgnoreCase("media:content"))
{
if(!atts.getValue("url").toString().equalsIgnoreCase("null")){
feedStr.setImgLink(atts.getValue("url").toString());
}
else{
feedStr.setImgLink("");
}
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equalsIgnoreCase("title"))
{
feedStr.setTitle(chars.toString());
}
else if (localName.equalsIgnoreCase("description"))
{
feedStr.setDescription(chars.toString());
}
else if (localName.equalsIgnoreCase("pubDate"))
{
feedStr.setPubDate(chars.toString());
}
else if (localName.equalsIgnoreCase("encoded"))
{
feedStr.setEncodedContent(chars.toString());
}
else if (qName.equalsIgnoreCase("media:content"))
{
}
else if (localName.equalsIgnoreCase("link"))
{
try {
feedStr.setUrl(new URL(chars.toString()));
}catch (Exception e){}
}
if (localName.equalsIgnoreCase("item")) {
rssList.add(feedStr);
feedStr = new RssFeedStructure();
articlesAdded++;
if (articlesAdded >= ARTICLES_LIMIT)
{
throw new SAXException();
}
}
}
public void characters(char ch[], int start, int length) {
chars.append(new String(ch, start, length));
}
public List<RssFeedStructure> getLatestArticles(String feedUrl) {
URL url = null;
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
url = new URL(feedUrl);
xr.setContentHandler(this);
xr.parse(new InputSource(url.openStream()));
} catch (IOException e) {
} catch (SAXException e) {
} catch (ParserConfigurationException e) {
}
return rssList;
}
}
I have used script below and the output is
X value : 123
Y value : 123
X value : 123
Y value : 130
how can I set first X as X0; first Y as Y0 and second X as X1 and second Y as Y1 ? I used SAX parser, it has processed my input file properly, and now i want to define X0, X1, Y0, Y1 in order to draw line
public static void main(String argv[]) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean xele = false;
boolean yele = false;
public void startElement(String uri, String localName,String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("X")) {
xele = true;
}
if (qName.equalsIgnoreCase("Y")) {
yele = true;
}
}
public void characters(char ch[], int start, int length) throws SAXException {
if (xele) {
System.out.println("X value : " + new String(ch, start, length));
xele = false;
}
if (yele) {
System.out.println("Y value : " + new String(ch, start, length));
yele = false;
}
}
};
saxParser.parse("c:\\input.xml", handler);
} catch (Exception e) {
e.printStackTrace();
}
Thanks
You can declare arrays to hold the values of X and Y and an index to increment after storing the values every time characters method is called by the parser, in your DefaultHandler implementation and expose these arrays through getters. Alternatively, you can use collections like java.util.List/java.util.ArrayList to hold the values.
public static void main(String argv[])
{
try
{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
MyDefaultHandler handler = new MyDefaultHandler();
saxParser.parse("c:\\input.xml", handler);
System.out.println(handler.getXList() + ", " + handler.getYList());
}
catch (Exception e)
{
e.printStackTrace();
}
}
static class MyDefaultHandler extends DefaultHandler
{
private List<Integer> xList = new ArrayList<Integer>();
private List<Integer> yList = new ArrayList<Integer>();
boolean xele = false;
boolean yele = false;
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
if (qName.equalsIgnoreCase("X"))
{
xele = true;
}
if (qName.equalsIgnoreCase("Y"))
{
yele = true;
}
}
public void characters(char ch[], int start, int length) throws SAXException
{
if (xele)
{
System.out.println("X value : " + new String(ch, start, length));
xele = false;
xList.add(Integer.parseInt(new String(ch, start, length)));
}
if (yele)
{
System.out.println("Y value : " + new String(ch, start, length));
yele = false;
yList.add(Integer.parseInt(new String(ch, start, length)));
}
}
public List<Integer> getXList()
{
return xList;
}
public List<Integer> getYList()
{
return yList;
}
};
I am trying to parse a UTF-8 xml file using SAX parser and i used the parser but it results an exception it's message "Expecting an element"
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<config>
<filepath>/mnt/sdcard/Audio_Recorder/anonymous22242.3gp</filepath>
<filename>anonymous22242.3gp</filename>
<annotation>
<file>anonymous22242.3gp</file>
<timestamp>0:06</timestamp>
<note>test1</note>
</annotation>
<annotation>
<file>anonymous22242.3gp</file>
<timestamp>0:09</timestamp>
<note>لول</note>
</annotation>
<annotation>
<file>anonymous22242.3gp</file>
<timestamp>0:09</timestamp>
<note>لولو</note>
</annotation>
</config>
private static String fileDirectory;
private final static ArrayList<String> allFileNames = new ArrayList<String>();
private final static ArrayList<String[]> allAnnotations = new ArrayList<String[]>();
private static String[] currentAnnotation = new String[3];
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser playbackParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean audioFullPath = false;
boolean audioName = false;
boolean annotationFile = false;
boolean annotationTimestamp = false;
boolean annotationNote = false;
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
System.out.println("Start Element :" + qName);
if (qName.equalsIgnoreCase("filepath")) {
audioFullPath = true;
}
if (qName.equalsIgnoreCase("filename")) {
audioName = true;
}
if (qName.equalsIgnoreCase("file")) {
annotationFile = true;
}
if (qName.equalsIgnoreCase("timestamp")) {
annotationTimestamp = true;
}
if (qName.equalsIgnoreCase("note")) {
annotationNote = 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 (audioFullPath) {
String filePath = new String(ch, start, length);
System.out.println("Full Path : " + filePath);
fileDirectory = filePath;
audioFullPath = false;
}
if (audioName) {
String fileName = new String(ch, start, length);
System.out.println("File Name : " + fileName);
allFileNames.add(fileName);
audioName = false;
}
if (annotationFile) {
String fileName = new String(ch, start, length);
currentAnnotation[0] = fileName;
annotationFile = false;
}
if (annotationTimestamp) {
String timestamp = new String(ch, start, length);
currentAnnotation[1] = timestamp;
annotationTimestamp = false;
}
if (annotationNote) {
String note = new String(ch, start, length);
currentAnnotation[2] = note;
annotationNote = false;
allAnnotations.add(currentAnnotation);
}
}
};
InputStream inputStream = getStream("http://www.example.com/example.xml");
Reader xmlReader = new InputStreamReader(inputStream, "UTF-8");
InputSource xmlSource = new InputSource(xmlReader);
xmlSource.setEncoding("UTF-8");
playbackParser.parse(xmlSource, handler);
System.out.println(fileDirectory);
System.out.println(allFileNames);
System.out.println(allAnnotations);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public Static InputStream getStream(String url)
{
try
{
connection = getConnection(url);
connection.setRequestProperty("User-Agent",System.getProperty("microedition.profiles"));
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
inputStream = connection.openInputStream();
return inputStream;
}
catch(Exception e)
{
System.out.println("NNNNNNN "+e.getMessage());
return null;
}
}
public HttpConnection getConnection(String url)
{
try
{
connection = (HttpConnection) Connector.open(url+getConnectionString());
}
catch(Exception e)
{
}
return connection;
}
but when i pass to the parse method the inputStream instead of inputSource it parses the file but still have a problem with Arabic characters between
playbackParser.parse(inputStream, handler);
The XML you showed has unencoded Arabic characters in it. That is in violation of the XML's declared Encoding, which means the XML is malformed. A SAX parser processes data piece by piece sequentially, triggering events for each piece. It will not detect such an encoding error until it reaches the piece that contains those erroneous characters. There is nothing you can do about that. The XML needs to be fixed by its original author.