i am trying to parse an xml file from an URL. I found an example in the following link
http://www.anddev.org/parsing_xml_from_the_net_-_using_the_saxparser-t353.html
and tried using it in my code but it returned the values to be as null
Following is my code of parsing xml
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
URL url = new URL("http://www.siva.com/search");
/** Handling XML */
SAXParserFactory saxparserfactory = SAXParserFactory.newInstance();
SAXParser saxparser = saxparserfactory.newSAXParser();
XMLReader xmlreader = saxparser.getXMLReader();
/* Create a new ContentHandler and apply it to the XML-Reader*/
ForListXMLHandler forlistmyhandler = new ForListXMLHandler();
xmlreader.setContentHandler(forlistmyhandler);
/* Parse the xml-data from our URL. */
xmlreader.parse(new InputSource(url.openStream()));
/* Parsing has finished. */
/* Our ExampleHandler now provides the parsed data to us. */
ParsedDataSet parsedDataSet = forlistmyhandler.getParsedData();
System.out.println(parsedDataSet.toString());
}
following is the code of MyXMLhandler
public class ForListXMLHandler extends DefaultHandler {
private boolean in_outertag = false;
private boolean in_innertag = false;
private boolean in_First_name = false;
private boolean in_Last_name = false;
private ParsedDataSet myParsedDataSet = new ParsedDataSet();
public ParsedDataSet getParsedData() {
return this.myParsedDataSet;
}
#Override
public void startDocument() throws SAXException {
this.myParsedDataSet = new ParsedDataSet();
}
#Override
public void endDocument() throws SAXException {
// Nothing to do
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
if (localName.equals("Searchdata")) {
this.in_outertag = true;
} else if (localName.equals("Searchdata")) {
this.in_innertag = true;
} else if (localName.equals("First_name")) {
this.in_First_name = true;
} else if (localName.equals("Last_name")) {
this.in_Last_name = true;
}
}
/**
* Gets be called on closing tags like:
* */
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if (localName.equals("Searchdata")) {
this.in_outertag = false;
} else if (localName.equals("Searchdata")) {
this.in_innertag = false;
} else if (localName.equals("First_name")) {
this.in_First_name = false;
} else if (localName.equals("Last_name")) {
// Nothing to do here
}
}
/**
* Gets be called on the following structure: characters
*/
#Override
public void characters(char ch[], int start, int length) {
if (this.in_First_name) {
myParsedDataSet.setfirstname(new String(ch, start, length));
}
if (this.in_Last_name) {
myParsedDataSet.setlastname(new String(ch, start, length));
}
}
}
next part is of my parsed data set class
public class ParsedDataSet {
private String First_name = null;
private String Last_name = null;
public String getFirstname() {
return First_name;
}
public void setfirstname(String First_name) {
this.First_name = First_name;
}
public String getlastname() {
return Last_name;
}
public void setlastname(String Last_name) {
this.Last_name = Last_name;
}
public String toString() {
return this.First_name + "n" + this.Last_name;
}
}
pls tell me where i am getting error
The endElement method gets fired before the characters method, so your boolean variables are always set to false when the characters method gets fired. You should move some code from endElement to characters, something like this:
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
}
#Override
public void characters(char ch[], int start, int length) {
if (this.in_First_name) {
this.in_First_name = false;
myParsedDataSet.setfirstname(new String(ch, start, length));
}
if (this.in_Last_name) {
this.in_Last_name = false;
myParsedDataSet.setlastname(new String(ch, start, length));
}
}
You should also take a look here for a complete explanation on "Working with XML on Android".
Related
I've got a java SAX Parser for XML (we set the date, make URL reqest for this date and parse XML file). Now I need to turn this code to web app in Tomcat. I've imported all nessessary libraries, created artefacts, but don't know how to change code itself.\
Here is initial code
Handler:
public class UserHandler extends DefaultHandler {
boolean bName = false;
boolean bValue = false;
String result=" ";
#Override
public void startElement(String uri,
String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("Valute")) {
String CharCode = attributes.getValue("CharCode");
} else if (qName.equalsIgnoreCase("Name")) {
bName = true;
} else if (qName.equalsIgnoreCase("Value")) {
bValue = true;
}
}
#Override
public void endElement(String uri,
String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("Valute")) {
System.out.print(" ");
}
}
#Override
public void characters(char ch[], int start, int length) throws SAXException {
if (bName) {
result=(new String(ch, start, length)+" ");
bName = false;
} else if (bValue) {
result=result+(new String(ch, start, length));
bValue = false;
System.out.print(result);
}
}
}
Main:
public static void main(String[] args) throws MalformedURLException {
//Set the date dd.mm.yyyy
String date="12.08.2020";
String link ="http://www.cbr.ru/scripts/XML_daily.asp?date_req=";
URL url =new URL(link);
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
UserHandler userHandler = new UserHandler();
saxParser.parse(String.valueOf(url+date), userHandler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
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
I have an XML file like this one:
<?xml version="1.0" encoding="UTF-8"?>
<Article>
<ArticleTitle>Java-SAX Tutorial</ArticleTitle>
<Author>
<FamilyName>Yong</FamilyName>
<GivenName>Mook</GivenName>
<GivenName>Kim</GivenName>
<nickname>mkyong</nickname>
<salary>100000</salary>
</Author>
<Author>
<FamilyName>Low</FamilyName>
<GivenName>Yin</GivenName>
<GivenName>Fong</GivenName>
<nickname>fong fong</nickname>
<salary>200000</salary>
</Author>
</Article>
I have tried the example in mkyong's tutorial here and I can retrieve data perfectly from it using SAX, it gives me:
Article Title : Java-SAX Tutorial
Given Name : Kim
Given Name : Mook
Family Name : Yong
Given Name : Yin
Given Name : Fong
Family Name : Low
But I want it to give me something like this:
Article Title : Java-SAX Tutorial
Author : Kim Mook Yong
Author : Yin Fong Low
In other terms, I would like to retrieve some of the child nodes of the node Author, not all of them, put them in a string variable and display them.
This is the class I use in order to parse the Authors with the modification I have tried to do:
public class ReadAuthors {
public void parse(String filePath) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean bFamilyName = false;
boolean bGivenName = false;
#Override
public void startElement(String uri, String localName,String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("FamilyName")) {
bFamilyName = true;
}
if (qName.equalsIgnoreCase("GivenName")) {
bGivenName = true;
}
}
#Override
public void endElement(String uri, String localName,
String qName) throws SAXException {
}
#Override
public void characters(char ch[], int start, int length) throws SAXException {
String fullName = "";
String familyName = "";
String givenName ="";
if (bFamilyName) {
familyName = new String(ch, start, length);
fullName += familyName;
bFamilyName = false;
}
if (bGivenName) {
givenName = new String(ch, start, length);
fullName += " " + givenName;
bGivenName = false;
}
System.out.println("Full Name : " + fullName);
}
};
saxParser.parse(filePath, handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
With this modification, it only gives me the ArticleTitle value and it doesn't return anything regarding the authors full names.
I have another class for parsing the ArticleTitle node and they are both called in a Main class.
What did I do wrong? And how can I fix it?
The fullName variable is overwritten everytime when the characters method is called. I think you should move out that variable into the handler: init with empty string when Author starts and write out when it ends. The concatenation should work as you did. I haven't tried this out but something similear should work:
public class ReadAuthors {
public void parse(String filePath) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean bName = false;
String fullName = "";
#Override
public void startElement(String uri, String localName,String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("FamilyName")) {
bName = true;
}
if (qName.equalsIgnoreCase("GivenName")) {
bName = true;
}
if (qName.equalsIgnoreCase("Author")) {
fullName = "";
}
}
#Override
public void endElement(String uri, String localName,
String qName) throws SAXException {
if (qName.equalsIgnoreCase("Author")) {
System.out.println("Full Name : " + fullName);
}
}
#Override
public void characters(char ch[], int start, int length) throws SAXException {
String name = "";
if (bName) {
name = new String(ch, start, length);
fullName += name;
bName = false;
}
}
};
saxParser.parse(filePath, handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
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 ...
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.