Parse a simple xml string - java

I have a simple xml and want to retrieve the value held in the 'String' which is either True or False. There are lots of suggested methods which look very complex! What would be the best way to do this?
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">"True"</string>
I am able to read the xml into an xmlReader as below.
XMLReader xmlReader = SAXParserFactory.newInstance()
.newSAXParser().getXMLReader();
InputSource source = new InputSource(new StringReader(response.toString()));
xmlReader.parse(source);
How would I now get the value out of the reader?

You will first need to define a Handler :
public class MyElementHandler extends DefaultHandler {
private boolean isElementFound = false;
private String value;
public String getValue() {
return value;
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equals("elem")) {
isElementFound = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) {
if (qName.equals("elem")) {
isElementFound = false;
}
}
#Override
public void characters(char ch[], int start, int length) {
if (isElementFound) {
value = new String(ch).substring(start, start + length);
}
}
}
Then, the you parse your xml as follows :
String xml = response.toString();
XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
InputSource source = new InputSource(new StringReader(xml));
//-- create handlers
MyAttributeHandler handler = new MyAttributeHandler();
xmlReader.setContentHandler(handler);
xmlReader.parse(source);
System.out.println("value = " + handler.getValue());
More general question about sax parsing.

Here one does not need XML. A two-liner:
String xmlContent = response.toString();
String value = xmlContent.replaceFirst("(?sm)^.*<string[^>]*>([^<]*)<.*$", "$1");
if (value == xmlContent) { // No replace
throw new IllegalStateException("Not found");
}
boolean result = Boolean.valueOf(value.trim().toLowerCase());
With XML one could do:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(inputSource);
String xml = doc.getDocumentElement().getTextContent();

Related

Java SAX is not parsing properly

I would appreciate any help on this.
This is my first handler I wrote.
I got I REST Webservice returning XML of links. It has quite simple structure and is not deep.
I wrote a handler for this:
public class SAXHandlerLnk extends DefaultHandler {
public List<Link> lnkList = new ArrayList();
Link lnk = null;
private StringBuilder content = new StringBuilder();
#Override
//Triggered when the start of tag is found.
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("link")) {
lnk = new Link();
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("link")) {
lnkList.add(lnk);
}
else if (qName.equals("applicationCode")) {
lnk.applicationCode = content.toString();
}
else if (qName.equals("moduleCode")) {
lnk.moduleCode = content.toString();
}
else if (qName.equals("linkCode")) {
lnk.linkCode = content.toString();
}
else if (qName.equals("languageCode")) {
lnk.languageCode = content.toString();
}
else if (qName.equals("value")) {
lnk.value = content.toString();
}
else if (qName.equals("illustrationUrl")) {
lnk.illustrationUrl = content.toString();
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
content.append(ch, start, length);
}
}
Some XML returned can be empty eg. or . When this happens my handler unfortunatelly adds previous value to the Object lnk. So when is empty in XML, I got lnk.illustrationUrl = content; equal to lnk.value.
Link{applicationCode='onedownload', moduleCode='onedownload',...}
In the above example, I would like moduleCode to be empty or null, because in XML it is an empty tag.
Here is the calling class:
public class XMLRepositoryRestLinksFilterSAXParser {
public static void main(String[] args) throws Exception {
SAXParserFactory parserFactor = SAXParserFactory.newInstance();
SAXParser parser = parserFactor.newSAXParser();
SAXHandlerLnk handler = new SAXHandlerLnk();
parser.parse({URL}, handler);
for ( Link lnk : handler.lnkList){
System.out.println(lnk);
}
}
}
Like stated in my comment, you'd do the following. The callbacks are usually called in startElement, characters, (nested?), characters, endElement order, where (nested?) represents an optional repeat of the entire sequence.
#Override
//Triggered when the start of tag is found.
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
content = null;
if (qName.equals("link")) {
lnk = new Link();
}
}
Note that characters may be called multiple times per a single XML element in your document, so your current code might fail to capture all content. You'd be better off using a StringBuilder instead of a String object to hold your character content and append to it. See this answer for an example.

How to handle namespaces with SAX Parser?

I'm trying to learn to parse XML documents, I have a XML document that uses namespaces so, I'm sure I need to do something to parse correctly.
This is what I have:
DefaultHandler handler = new DefaultHandler() {
boolean bfname = false;
boolean blname = false;
boolean bnname = false;
boolean bsalary = 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;
}
if (qName.equalsIgnoreCase("LASTNAME")) {
blname = true;
}
if (qName.equalsIgnoreCase("NICKNAME")) {
bnname = true;
}
if (qName.equalsIgnoreCase("SALARY")) {
bsalary = 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;
}
if (blname) {
System.out.println("Last Name : " + new String(ch, start, length));
blname = false;
}
if (bnname) {
System.out.println("Nick Name : " + new String(ch, start, length));
bnname = false;
}
if (bsalary) {
System.out.println("Salary : " + new String(ch, start, length));
bsalary = false;
}
}
};
saxParser.parse(file, handler);
My question is, how I can handle the namespase in this example?
To elaborate on what Blaise's point with sample code, consider this contrived example:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ns.xml -->
<root xmlns:foo="http://data" xmlns="http://data">
<foo:record>ONE</foo:record>
<bar:record xmlns:bar="http://data">TWO</bar:record>
<record>THREE</record>
<record xmlns="http://metadata">meta 1</record>
<foo:record xmlns:foo="http://metadata">meta 2</foo:record>
</root>
There are two different types of record element. One in the http://data namespace; the other in http://metadata namespace. There are three data records and two metadata records.
The document could be normalized to this:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:root xmlns:ns0="http://data" xmlns:ns1="http://metadata">
<ns0:record>ONE</ns0:record>
<ns0:record>TWO</ns0:record>
<ns0:record>THREE</ns0:record>
<ns1:record>meta 1</ns1:record>
<ns1:record>meta 2</ns1:record>
</ns0:root>
But the code must handle the general case.
Here is some code for printing the metadata records:
class MetadataPrinter extends DefaultHandler {
private boolean isMeta = false;
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
isMeta = "http://metadata".equals(uri) && "record".equals(localName);
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (isMeta) {
System.out.println();
isMeta = false;
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (isMeta) {
System.out.print(new String(ch, start, length));
}
}
}
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
SAXParser parser = factory.newSAXParser();
parser.parse(new File("ns.xml"), new MetadataPrinter());
Note: namespace awareness must be enabled explicitly in some of the older Java XML APIs (SAX and DOM among them.)
In a namespace qualified XML document there are two components to a nodes name: namespace URI and local name (these are passed in as parameters to the startElement and endElement events). When you are checking for the presence of an element you should be matching on both these parameters. Currently your code would work for both documents below even though they are namespace qualified differently.
<foo xmlns="FOO">
<bar>Hello World</bar>
</foo>
And
<foo xmlns="BAR">
<bar>Hello World</bar>
</foo>
You are currently (and incorrectly) matching on the qName parameter. The problem with what you are doing is that the qName might change based on the prefix used to represent a namespace. The two documents below have the exact same namespace qualification. The local names and namespaces are the same, but their QNames are different.
<foo xmlns="FOO">
<bar>Hello World</bar>
</foo>
And
<ns:foo xmlns:ns="FOO">
<ns:bar>Hello World</ns:bar>
<ns:foo>

not able to add data while parsing xml data using SAXParser

I am tryin to get rss feed using xml parsing and
I am getting problem while parsing xml data using SAXParser
I have tried something like
In my MainActivity.java
try{
/****** Creating a new instance of the SAX parser ****************/
SAXParserFactory saxPF = SAXParserFactory.newInstance();
SAXParser saxParser = saxPF.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
URL url = new URL("http://ibnlive.in.com/ibnrss/rss/world/world.xml");
myXMLHandler = new FeedsXMLHandler();
xmlReader.setContentHandler(myXMLHandler);
xmlReader.parse(new InputSource(url.openStream()));
}catch (Exception e) {
e.printStackTrace();
}
I am retriving data from my handler using
ArrayList<FeedsItems> feedsData = myXMLHandler.getXMLData();
Log.v("size",Integer.toString(feedsData.size()));
Here its showing size as zero.
My FeedsXMLHandler.java
private ArrayList<FeedsItems> dataArray = new ArrayList<FeedsItems>();
private FeedsItems data = null;
#Override
public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException
{
elementValue = "";
elementOn = true;
if (localName.equalsIgnoreCase("rss"))
{
// data = new FeedsItems();
}
else if (localName.equalsIgnoreCase("item"))
{
data = new FeedsItems();
Log.v("Item","I am in item block");
}
else if (localName.equalsIgnoreCase("description"))
{
bufferDesc = new StringBuilder();
elementOn = true;
}
else if (localName.equalsIgnoreCase("title"))
{
bufferTitle = new StringBuilder();
elementOn = true;
}
else if(localName.equalsIgnoreCase("link"))
{
bufferLink = new StringBuilder();
elementOn = true;
}
}
/*********** Method will be called when the tags of the XML end **************/
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
elementOn = false;
/*** Sets the values after retrieving the values from the XML tags ******/
if (localName.equalsIgnoreCase("title"))
{
elementOn = false;
data.setTitle(bufferTitle.toString());
bufferTitle.delete(0,bufferTitle.length());
}
else if (localName.equalsIgnoreCase("link")){
elementOn = false;
data.setFeedsUrl(bufferLink.toString());
bufferLink.delete(0,bufferLink.length());
}
else if (localName.equalsIgnoreCase("description")){
elementOn = false;
data.setDescription(bufferDesc.toString());
bufferDesc.delete(0, bufferDesc.length());
}
else if (localName.equalsIgnoreCase("item")){
dataArray.add(data);
}
}
I am not able to understand whats wrong in it. I have already implemented xml parsing using SAXParser in this method. Any help or suggestion will be welcome

null pointer exception using SAX XML Parser

I am using the SAX Parser for XML Parsing. The problem is if I print, everything is fine. However, If I want to save anything, I get this error message (with the typos):
"XML Pasing Excpetion = java.lang.NullPointerException"
My code is given below:
Parser code:
try {
/** Handling XML */
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
/** Send URL to parse XML Tags */
URL sourceUrl = new URL(
"http://50.19.125.224/Demo/VeryGoodSex_and_the_City_S6E6.xml");
/** Create handler to handle XML Tags ( extends DefaultHandler ) */
MyXMLHandler myXMLHandler = new MyXMLHandler();
xr.setContentHandler((ContentHandler) myXMLHandler);
xr.parse(new InputSource(sourceUrl.openStream()));
} catch (Exception e) {
System.out.println("XML Pasing Excpetion = " + e);
}
Object to hold XML parsed Info:
public class ParserObject {
String name=null;
String description=null;
String bitly=null; //single
String productLink=null;//single
String productPrice=null;//single
Vector<String> price=null;
}
Handler class:
static ParserObject[] xmlDataObject = null;
public void endElement(String uri, String localName, String qName)
throws SAXException {
currentElement = false;
if (qName.equalsIgnoreCase("title"))
{
xmlDataObject[index].name=currentValue;
}
else if (qName.equalsIgnoreCase("artist"))
{
xmlDataObject[index].artist=currentValue;
}
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentElement = true;
if (qName.equalsIgnoreCase("allinfo"))
{
System.out.println("started");
}
else if (qName.equalsIgnoreCase("tags"))
{
insideTag=1;
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
if (currentElement) {
currentValue = new String(ch, start, length);
currentElement = false;
}
}
Your ParserObject array i.e xmlDataObject is having null value thats is why it is showing null pointer exception. This is my View and it might be wrong but once check it too.

xml parsing from String

I am parsing a xml the data is coming from a String. i am using the following code for parsing:-
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docBuilderFactory
.newDocumentBuilder();
docBuilder.isValidating();
ByteArrayInputStream ba= new ByteArrayInputStream(connect.content.getBytes("UTF-8"));
doc = docBuilder.parse(ba);
doc.getDocumentElement().normalize();
NodeList locationStatus = doc.getElementsByTagName("street");
for (int i = 0; i < locationStatus.getLength(); i++) {
Node locationValue = locationStatus.item(i).getChildNodes().item(0);
_node.addElement(locationValue.getNodeValue());
}
String [] nodeString = new String[_node.size()];
_node.copyInto(nodeString);
add(new LabelField(nodeString.length+""));
But this code is giving error , i dont no where the error is.
please Help me out
Thanks in advance
Use XStream or JAXB
did u tried this way?
SAXParserImpl saxparser = new SAXParserImpl();
ResponseHandler handler = new ResponseHandler();
ByteArrayInputStream stream = new ByteArrayInputStream(xmlresp.getBytes());
public class ResponseHandler extends DefaultHandler
{
public void startElement(String uri, String localName,
String qName,Attributes attributes) {}
public void characters(char[] ch, int start, int length)
{
tempVal = new String(ch, start, length);
}
public void endElement(String uri, String localName,
String qName) throws SAXException {}
}

Categories