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;
}
};
Related
I am have below xml structure
<fs:AsReportedItem>
<fs:BookMark>/BODY[1]/DIV[3135]/DIV[0]/TABLE[0]/TBODY[0]/TR[32]/TD[5]/DIV[0]/FONT[0]/substr(1,2)
</fs:BookMark>
</fs:AsReportedItem>
I am parsing using SAX and reading tax value in the endElement() method
Here is my sample code
private void parseDocument() {
// parse
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(FileName, this);
} catch (ParserConfigurationException e) {
System.out.println("ParserConfig error");
} catch (SAXException e) {
System.out.println("SAXException : xml not well formed");
} catch (IOException e) {
System.out.println("IO error");
}
}
public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {
if (OrgDataPartitonObj != null && "fs:FinancialStatementLineItemDataItem".equals(OrgDataPartitonObj.getType())) {
FinancialStatementLineItemParser.startFinancialStatementLineItemParser(OrgDataPartitonObj,financialStatementLineItemObj, elementName, attributes);
}
}
public void endElement(String s, String s1, String element) throws SAXException {
if (OrgDataPartitonObj != null && "fs:FinancialStatementLineItemDataItem".equals(OrgDataPartitonObj.getType())) {
FinancialStatementLineItemParser.getEndElementFinancialStatementLineItemParser(financialStatementLineItemObj, element, tmpValue);
}
}
public static void getEndElementFinancialStatementLineItemParser(FinancialStatementLineItem financialStatementLineItemObj, String element, String tmpValue) {
if (element.equals("fs:BookMark")) {
financialStatementLineItemObj.setBookMark(tmpValue);
}
}
#Override
public void characters(char[] buffer, int start, int length) {
tmpValue = new String(buffer, start, length);
}
When i debug then i can see only this value /substr(1,2) all value with "/" is escaped
I dont know why i am not getting full value /BODY[1]/DIV[3135]/DIV[0]/TABLE[0]/TBODY[0]/TR[32]/TD[5]/DIV[0]/FONT[0]/substr(1,2)
If any escape character is used then where i have to use .
Here the sourcecode for a DefaultHandler which collects the text:
private static DefaultHandler getHandler() {
return new DefaultHandler() {
String text;
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if ("BookMark".equals(qName)) {
text = "";
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
text += new String(ch).trim();
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("BookMark".equals(qName)) {
System.out.println("endElement: " + text);
}
}
};
}
You need to change your characters()-method to
#Override
public void characters(char[] buffer, int start, int length) {
tmpValue += new String(buffer, start, length);
}
and you must reset tmpValue in the startElement()-method to "".
Just change character() method
#Override
public void characters(char[] buffer, int start, int length) {
tmpValue += new String(buffer, start, length);
}
And add this at last line in the endElement method .
public void endElement(String s, String s1, String element) throws SAXException {
if (OrgDataPartitonObj != null && "fs:FinancialStatementLineItemDataItem".equals(OrgDataPartitonObj.getType())) {
FinancialStatementLineItemParser.getEndElementFinancialStatementLineItemParser(financialStatementLineItemObj, element, tmpValue);
}
tmpValue="";
}
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.
I have XML file and I want to get position of a node.
<Root>
<Node1></Node1>
</Root>
I want to get 1) start and end positions; 2) start and end lines
How to do that? Thanks
Create a Reader that keeps track of position information you want:
static public class MyReader extends Reader {
final private Reader internalReader;
private int pos;
private int line;
public MyReader(Reader internalReader) {
this.internalReader = internalReader;
}
public int getPos() {
return pos;
}
public int getLine() {
return line;
}
#Override
public int read(char[] cbuf, int off, int len) throws IOException {
int chars_read = internalReader.read(cbuf, off, 1);
pos += chars_read;
if(cbuf[off] =='\n' && chars_read > 0) {
line++;
}
return chars_read;
}
#Override
public void close() throws IOException {
internalReader.close();
}
}
Use that with a ContentHandler that stores the position information in some data structure associated with the elements.
String xmlString = "<Root>\n"
+ " <Node1></Node1>\n"
+ "</Root>";
StringReader strReader = new StringReader(xmlString);
MyReader reader = new MyReader(strReader);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
Map<String,List<Integer>> startMap = new HashMap<>();
Map<String,List<Integer>> endMap = new HashMap<>();
Map<String,List<Integer>> startLineMap = new HashMap<>();
Map<String,List<Integer>> endLineMap = new HashMap<>();
DefaultHandler handler = new DefaultHandler() {
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName); //To change body of generated methods, choose Tools | Templates.
List<Integer> l = endMap.get(qName);
if(null == l) {
l = new ArrayList<>();
}
l.add(reader.getPos());
endMap.put(qName, l);
List<Integer> ll = endLineMap.get(qName);
if(null == ll) {
ll= new ArrayList<>();
}
ll.add(reader.getLine());
endLineMap.put(qName, ll);
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes); //To change body of generated methods, choose Tools | Templates.
List<Integer> l = startMap.get(qName);
if(null == l) {
l = new ArrayList<>();
}
l.add(reader.getPos());
startMap.put(qName, l);
List<Integer> ll = startLineMap.get(qName);
if(null == ll) {
ll= new ArrayList<>();
}
ll.add(reader.getLine());
startLineMap.put(qName, ll);
}
};
xmlreader.setContentHandler(handler);
xmlreader.parse(new InputSource(reader));
System.out.println("startMap = " + startMap);
System.out.println("endMap = " + endMap);
System.out.println("startLineMap = " + startLineMap);
System.out.println("endLineMap = " + endLineMap);
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.
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));
}