JAK generated KML not work with Google My Maps - java

I write manually a KML file trying to import some polygons in MyMaps. This way works fine:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<Placemark>
<Style>
<PolyStyle>
<color>#a00000ff</color>
<outline>0</outline>
</PolyStyle>
</Style>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>9.184254,45.443636 9.183379,45.434288 9.224836,45.431499 9.184254,45.443636</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
I try to write a java program using JAK that generate a most possibile equal file, but it doesn't work with Maps
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:kml xmlns:atom="http://www.w3.org/2005/Atom" xmlns:ns3="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
<ns3:Document>
<ns3:Placemark>
<ns3:Style>
<ns3:PolyStyle>
<ns3:color>#EABCFF</ns3:color>
<ns3:outline>0</ns3:outline>
</ns3:PolyStyle>
</ns3:Style>
<ns3:Polygon>
<ns3:innerBoundaryIs>
<ns3:LinearRing>
<ns3:coordinates>9.184254,45.443636 9.183379,45.434288 9.224836,45.431499 9.184254,45.443636</ns3:coordinates>
</ns3:LinearRing>
</ns3:innerBoundaryIs>
</ns3:Polygon>
</ns3:Placemark>
</ns3:Document>
</ns3:kml>
That's program:
public static void main(String[] args) throws IOException {
// Style
PolyStyle polystyle = KmlFactory.createPolyStyle();
polystyle.setColor("#EABCFF");
// polystyle.setFill(true);
polystyle.setOutline(false);
//
Kml kml = KmlFactory.createKml();
Document document = kml.createAndSetDocument();
Placemark pm = document.createAndAddPlacemark();
LinearRing linearRing = pm.createAndSetPolygon().createAndAddInnerBoundaryIs().createAndSetLinearRing();
linearRing.addToCoordinates(9.184254, 45.443636, 0);
linearRing.addToCoordinates(9.183379, 45.434288, 0);
linearRing.addToCoordinates(9.224836, 45.431499, 0);
linearRing.addToCoordinates(9.184254, 45.443636, 0);
pm.createAndAddStyle().setPolyStyle(polystyle);
//
kml.marshal(new FileWriter("D:/prova.kml"));
}

I view <ns3: in your kml this make the kml invalid for google maps
Try to correct the file

I had the same problem.
Instead of using kml.marshal(new FileWriter("D:/prova.kml")); I did this...
String name = kml.getClass().getSimpleName();
if ("Kml".equals(name)) {
name = name.toLowerCase();
}
JAXBContext jaxbContext = JAXBContext.newInstance(Kml.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NameSpaceBeautyfier());
JAXBElement<Kml> jaxbKml = new JAXBElement<>(new QName("http://www.opengis.net/kml/2.2", name), (Class<Kml>) kml.getClass(), kml);
jaxbMarshaller.marshal(jaxbKml, file);
With a NameSpaceBeautifier like this ...
private static final class NameSpaceBeautyfier extends NamespacePrefixMapper {
private static final String KML_PREFIX = ""; // DEFAULT NAMESPACE
private static final String KML_URI= "http://www.opengis.net/kml/2.2";
#Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if(KML_URI.equals(namespaceUri)) {
return KML_PREFIX;
}
return suggestion;
}
#Override
public String[] getPreDeclaredNamespaceUris() {
return new String[] { KML_URI };
}
private NameSpaceBeautyfier() {
}
}
Hope this helps..

Related

Null Pointer Exception while unmarshalling XML with #XmlAnyElement annotation

I'm currently trying to unmarshal some XML into a java object using JAXB and I'm getting a strange Null Pointer Exception. This is only an issue while unmarshalling. I can marshal with these classes just fine. Here are the relevant pieces of code (irrelevant portions are denoted by "..."):
The JAXB Root element:
...
#XmlRootElement(name="assets")
public class Assets {
String product;
Images images = new Images();
...
Public Assets() {}
...
public String getProduct() { return this.product; }
#XmlAttribute(name="product")
public void setProduct(String newProduct) { this.product = newProduct; }
public Images getImages() { return this.images; }
#XmlElement(name="images")
public void setImages(Images newImages) { this.images = newImages; }
...
}
The Images sub-element of the root element:
...
#XmlRootElement(name="images")
#XmlSeeAlso(Image.class)
#XmlType(propOrder = {"mainAsset", "image"})
public class Images {
List<Image> images;
Image mainAsset;
private static char counter = 'a';
private static final String prefix = "product-image-";
// Here's the part that causes the NPE
#XmlAnyElement(lax=true)
public List<JAXBElement<Image>> getImage() {
final List<JAXBElement<Image>> imageList = new ArrayList<JAXBElement<Image>>();
for (final Image g : this.images) {
imageList.add(new JAXBElement(new QName(prefix + counter++), Image.class, g));
}
counter = 'a';
return imageList;
}
#XmlElement(name="renditions")
public void setImage(List<Image> newImages) { this.images = newImages; }
public Image getMainAsset() { return this.mainAsset; }
#XmlElement(name="main-asset-name")
public void setMainAsset(Image newMainAsset) { this.mainAsset = newMainAsset; }
}
The logic for unmarshalling the XML:
...
public void modifyXML() {
try {
JAXBContext context = JAXBContext.newInstance(Assets.class, Images.class, Image.class);
Unmarshaller um = context.createUnmarshaller();
File f = new File("/path/to/my.xml");
Assets assets = (Assets) um.unmarshal(f);
...
} catch (JAXBException e) {
e.printStackTrace();
}
}
...
Finally, the XML I'm trying to unmarshal (it might help to know that this xml file was actually generated using the JAXB marshaller, which runs without any problems):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assets product="TEST PRODUCT">
<images>
<main-asset-name>
<path>stuff.jpg</path>
<title>theTitle</path>
<alt>theAlt</path>
<description>theDescription</description>
</main-asset-name>
<product-image-a>
<path>48x48.jpg</path>
<title>theTitle</path>
<alt>theAlt</path>
<description>theDescription</description>
</product-image-a>
<product-image-b>
<path>140x140.jpg</path>
<title>theTitle</path>
<alt>theAlt</path>
<description>theDescription</description>
</product-image-b>
<product-image-c>
<path>1280x1280.jpg</path>
<title>theTitle</path>
<alt>theAlt</path>
<description>theDescription</description>
</product-image-c>
<product-image-d>
<path>319x319.jpg</path>
<title>theTitle</path>
<alt>theAlt</path>
<description>theDescription</description>
</product-image-d>
</images>
</assets>
Okay, so that's all the relevant code (I think). When I run my program, I get the following error right after invoking the unmarshaller:
java.lang.NullPointerException
at com.my.companys.name.Images.getImage(Images.java:25)
And the line number referenced is the line where the for loop starts in my Images.java class file.
Does anyone have any ideas why this.images might be null here? Any help is greatly appreciated. Thanks ahead of time.
Here's the solution I've been using for now. It's a bit of a hack, but hell... It does the job.
First, I get the raw xml as a string instead of reading it as a file:
public void modifyXML() {
try {
JAXBContext context = JAXBContext.newInstance(Assets.class, Image.class);
Unmarshaller um = context.createUnmarshaller();
// This xml should be formatted in a way that JAXB can work with
String rawXML = getRawXML("/path/to/my.xml");
// Hand the modified xml to the unmarshaller
Assets umAssets = (Assets) um.unmarshal(new StreamSource(new StringReader(rawXML)));
// Do stuff with umAssets
...
} catch (Exception e) {
e.printStackTrace();
}
}
private String getRawXML(String path) throws IOException {
String xml = readFile(path, StandardCharsets.UTF_8);
// This should make it so JAXB can handle the xml properly
xml = xml.replaceAll("<main-asset-name>", "<image>");
xml = xml.replaceAll("</main-asset-name>", "</image>");
xml = xml.replaceAll("<product-image.*>", "<image>");
return xml.replaceAll("</product-image.*>", "</image>");
}
private String readFile(String path, Charset encoding) throws IOException {
// A simple file reader
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
This seems to do the trick, so I'm going to use this for now. Of course, I'm still open to better solutions if anyone has one.

Xstream isn't attaching an alias for the field

I've defined my xstream like so:
public static final String listToXMLTree(List<?> list,
Class<?> domainClass, Converter evtConverter ) {
String xml = "";
StringBuffer buff = new StringBuffer(1000);
buff.append("<?xml version='1.0' encoding='iso-8859-1'?>");
XStream xstream = new XStream(new DomDriver());
if (list != null && list.size() > 0) {
xstream.registerConverter(evtConverter);
xstream.alias("rows", List.class);
xstream.alias("row", Event.class );
xstream.aliasField("child", Event.class, "hasChildren");
xml = xstream.toXML(list);
} else {
buff.append("<rows/>");
}
xml = buff.append(xml).toString();
System.out.println(xml);
return xml;
}
But the xml that pops out doesn't have any alias for the "hasChildren" variable - why so? The xml looks like this:
<?xml version='1.0' encoding='iso-8859-1'?>
<rows>
<row id="Puerto Rico692014-04-30 00:00:00.02014-07-29 00:00:00.0" xmlkids="1">
<cell></cell>
<cell>Puerto Rico</cell>
<cell>103415</cell>
</row>
</rows>
EDIT
This is the event class that I have - (on a seperate note I tried using the XStream aliases and removed the code above that creates them manually but it didn't work either):
public class Event
{
// Event parameters
private String region;
private boolean hasChildren;
public boolean isHasChildren() {
return hasChildren;
}
public void setHasChildren(boolean hasChildren) {
this.hasChildren = hasChildren;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
}
The evtConverter is a converter that maps the xml that Xstream spits out onto a DHTMLx grid.
Thanks
Credit for this answer goes to Vertex - the converter needed to be added after the aliases in order to work properly - I actually refactored my answer and have the object making use of the Xstream annotations instead of defining them in the method. Here's the code:
/**
* Method to convert list objects to XML using XStream API.
* <p>
*
* #param list
* #param domainClass
* #param columnIds
*/
public static final String listToXML(List<?> list, Class<?> domainClass,
Converter converter) {
String xml = "";
StringBuffer buff = new StringBuffer(1000);
buff.append("<?xml version='1.0' encoding='UTF-8'?>");
XStream xstream = new XStream(new DomDriver());
if (list != null && list.size() > 0) {
xstream.alias("rows", List.class);
xstream.processAnnotations(domainClass);
xstream.registerConverter(converter);
xml = xstream.toXML(list);
} else {
buff.append("<rows/>");
}
xml = buff.append(xml).toString();
return xml;
}

XStream, Aliasing and "DuplicateFieldException"

I'm trying to write an app so that it is able to read this kind of XML and create an entire object based on it;
<actor id="id273211" PGFVersion="0.19" GSCVersion="0.10.4">
<attributes>
<text id="name">Actor 1b</text>
<point id="position">
<real id="x">0</real>
<real id="y">0</real>
</point>
</attributes>
</actor>
My problem is I'm aliasing members of the class Point as "real" and it gives an exception.
What I have now is;
#XStreamAlias("actor")
public class Actor {
#XStreamAsAttribute
String id = "",PGFVersion = "", GSCVersion = "";
Attributes attributes = new Attributes();
}
public class Attributes {
public Text text = new Text("name", "Actor 1");
public Point point = new Point();
}
#XStreamConverter(value=ToAttributedValueConverter.class, strings={"value"})
#XStreamAlias("text")
public class Text {
#XStreamAsAttribute
String id;
String value;
public Text(String text, String value) {
this.id = text;
this.value = value;
}
public class Point {
#XStreamAlias("real")
public Real x = new Real("x", "11");
#XStreamAlias("real")
public Real y = new Real("y", "21");
#XStreamAsAttribute
public String id = "position";
}
And my Test.java:
public static void main(String[] args) throws Exception {
XStream xstream = new XStream();
Actor actor2 = new Actor();
xstream.processAnnotations(Text.class);
xstream.processAnnotations(Real.class);
xstream.processAnnotations(Point.class);
xstream.processAnnotations(Actor.class);
String xml = xstream.toXML(actor2);
System.out.println(xml);
}
This outputs XML perfectly, as follows:
<actor id="" PGFVersion="" GSCVersion="">
<attributes>
<text id="name">Actor 1</text>
<point id="position">
<real id="x">11</real>
<real id="y">21</real>
</point>
</attributes>
</actor>
But when I try to import it using:
String xml = xstream.toXML(actor2);
Actor actorNew = (Actor)xstream.fromXML(xml);
System.out.println(xml);
It gives an exception:
Exception in thread "main" com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$DuplicateFieldException:
Duplicate field y
---- Debugging information ---- field : y class : projectmerger1.Point required-type : projectmerger1.Point
converter-type :
com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path : /projectmerger1.Actor/attributes/point/real[2]
line number : 6 class[1] :
projectmerger1.Attributes class[2] : projectmerger1.Actor
version : 1.4.6
Is this a wrong setup as a whole or can I continue using it with some tweaks?
I solved it by changing in Point class;
public class Point {
/*
#XStreamAlias("real")
#XStreamAlias("real2")
public Real y = new Real("y", "21");
#XStreamAsAttribute
public String id = "position";
*/
#XStreamImplicit
public List xy = new ArrayList();
public void add(Real entry) {
xy.add(entry);
}
}
and adding this to my Test.java:
actor2.attributes.point.add(new Real("x","0"));
actor2.attributes.point.add(new Real("y","0"));
I'll keep experimenting with this. Thanks for the support.

How to get Embeded/nested XML from a big XML file using SAX parser

We are performing some operations on embedded/Nested XML.I am using SAXParser to parse the entire XML file.I want to get the entire nested XML with tags and value.For example my XML looks like.
I want entire XML within the <ANY_ELEMENT>.....</ANY-ELEMENT> tag.
<?xml version="1.0" encoding="UTF-8"?>
<x:xMessage xmlns:x="http://www.connecture.com/integration/x" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.connecture.com/integration/x xMessageWrapper.xsd
">
<x:xMessageHeader>
<Version>850</Version>
<Source>Source</Source>
<Target>target</Target>
<Timestamp>2013-12-31T12:00:00</Timestamp>
<RequestID>123456</RequestID>
<ResponseID>54321</ResponseID>
<Priority>3</Priority>
<Username>Deepak</Username>
<Password>Kumar</Password>
</x:xMessageHeader>
<x:xMessageBody>
<ANY-ELEMENT>
<xEnveloped_834A1 xsi:schemaLocation="....." xmlns="......."
..........................
..........................
some Complex XML
..........................
..........................
..........................
</ANY-ELEMENT>
</x:XMessageBody>
</x:XMessage>
Handler class Sample code:
public class MessageWrapperHandler extends DefaultHandler {
private boolean bActualMessage = false;
private String actualMessage = null;
private long lengthActualMessage=0;
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equalsIgnoreCase("ANY-ELEMENT")) {
bActualMessage = true;
//lengthActualMessage=How to know the length of Child XML
}
}
public void characters(char ch[], int start, int length) {
if (bActualMessage) {
actualMessage = new String(ch, start, length);
//trying to get embedded XML
bActualMessage = false;
}
}
}
But since next element after is XML content so giving me nothing.SO How to achieve it.
EDIT: You are free to modify XML after <ANY-ELEMENT> like adding contents into CDATA
Instead of SAX, I would recommend using StAX (a StAX implementation is included in the JDK/JRE since Java SE 6). StAX is similar to SAX except instead of having the events pushed to you, you pull (request) them.
In the code below the XMLStreamReader is advanced to the ANY-ELEMENT element. Once it is at the correct position you can interact with it as you wish.
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xmlSource = new StreamSource("src/forum19559825/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xmlSource);
Demo demo = new Demo();
demo.positionXMLStreamReaderAtAnyElement(xsr);
demo.processAnyElement(xsr);
}
private void positionXMLStreamReaderAtAnyElement(XMLStreamReader xsr) throws Exception {
while(xsr.hasNext()) {
if(xsr.getEventType() == XMLStreamReader.START_ELEMENT && "ANY-ELEMENT".equals(xsr.getLocalName())) {
break;
}
xsr.next();
}
}
private void processAnyElement(XMLStreamReader xmlStreamReaderAtAnyElement) {
// TODO: Stuff
System.out.println("FOUND IT");
}
}

XML parsing problem in android using android.sax

I have an xml file as
<?xml version="1.0" encoding="utf-8"?>
<sections>
<section>
<name>Most Pouplar</name>
<items>
<item pos="1">
<name>
AcaiBerry Diet
</name>
<description>
<![CDATA[
Natrol AcaiBerry Diet supports weight loss goals when combined with a healthy reduced-calorie diet and exercise program. Acai is a wild fruit harvested in the rain forests of Brazil recognized for its high ORAC (oxygen-radical absorbance capacity) value - a measure of its antioxidant capacity. An adequate intake of antioxidants helps neutralize harmful free radicals that are produced by the body as a result of regular exercise.
]]>
</description>
</item>
<item pos="2">
<name>
AcaiBerry Weekend Cleanse
</name>
<description>
<![CDATA[
AcaiBerry Weekend Cleanse is a 3-step, easy-to-use cleansing program. Step 1 helps minimize occasional constipation/bloating, step 2 helps reduce toxins via antioxidant protection & cell regeneration and step 3 helps to restore the friendly bacteria that protect & strengthen the GI tract.
]]>
</description>
</item>
<item pos="4">
<name>
Carb Intercept Phase 2 + Chromium
</name>
<description>
<![CDATA[
Natrol Carb Intercept supports a low-carb lifestyle by controlling carbohydrates found in breads, cereals, rice, pasta and other starch-containing foods. Each serving provides 1,000mg of Phase 2 Carb Controller; a clinically tested ingredient that inhibits the enzyme responsible for digesting starch into simple sugars your body can absorb.
]]>
</description>
</item>
<item pos="3">
<name>
Resveratrol Diet
</name>
<description>
<![CDATA[
Losing weight has never been so rejuvenating! Natrol introduces Resveratrol Diet, a complex blend of antioxidants, enzymes and other nutrientsto help boost your metabolism and promote calorie burning.
]]>
</description>
</item>
</items>
</section>
<section>
<name>Least Popular</name>
<items>
<item pos="1">
<name>
Advanced Sleep Melatonin 10mg Maximum Strength
</name>
<description>
<![CDATA[
Getting a good night's sleep is even easier with Natrol Melatonin - a natural nightcap. A hormone found in the body, melatonin, helps promote more restful sleep. Natrol Melatonin provides relief for occasional sleeplessness, and helps promote a more relaxing night and better overall health.
]]>
</description>
</item>
<item pos="2">
<name>
Sleep 'N Restore
</name>
<description>
<![CDATA[
If you need to feel more rested due to lack of sleep, try Natrol Sleep 'N Restore. Sleep 'N Restore helps promote a more restful, deeper sleep, while supporting your body's natural restoration processes.* A combination of melatonin and valerian, this natural sleep aide includes antioxidants that can help your body protect its cells from damage to help you restore and recharge while you sleep.
]]>
</description>
</item>
</items>
</section>
</sections>
I defined a POJO as
public class ItemPojo {
//Fields of an item
private String itemName;
private String itemDescription;
private int itemPosition;
//Getters and Setters
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getItemDescription() {
return itemDescription;
}
public void setItemDescription(String itemDescription) {
this.itemDescription = itemDescription;
}
public int getItemPosition() {
return itemPosition;
}
public void setItemPosition(int itemPosition) {
this.itemPosition = itemPosition;
}
}
I am implementing a method for parsing xml file, but I have no idea about how can I read multiple <item> tag, which are within <items> tag.
Edited
I am putting part of code, which I am trying
//Store all items with a particular section
ArrayList<ItemPojo> itemList = new ArrayList<ItemPojo>();
//Store all items categorized by section
Map<String, ArrayList<ItemPojo>> itemStore = new HashMap<String, ArrayList<ItemPojo>>(1);
//Single item
ItemPojo currentItem = null;
//Current section name
String sectionName = null;
public AndroidSaxFeedParser() {
super();
}
public void parse() { //Map<String, ArrayList<ItemPojo>>
RootElement root = new RootElement(SECTIONS);
Element section = root.getChild(SECTION);
Element itemHeader = section.getChild(ITEM_HEADER);
//Read <name> tag as used as section
itemHeader.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
sectionName = body;
}
});
//TODO set item header here
Element items = section.getChild(ITEMS);
Element item = items.getChild(ITEM);
/*//Put all items of same category
items.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
//sort item with position
Collections.sort(itemList, ItemPojo.COMPARE_BY_POSITION);
//Putting it into master list
itemStore.put(sectionName, itemList);
//And clear the item list
itemList.clear();
}
});*/
item.setStartElementListener(new StartElementListener() {
public void start(Attributes attributes) {
currentItem = new ItemPojo();
Log.i("Test xml", "item initalised " + currentItem.toString());
}
});
item.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
// TODO Auto-generated method stub
itemList.add(currentItem);
Log.i("Test xml", "New items found " + currentItem.toString());
}
});
item.getChild(ITEM_NAME).setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
currentItem.setItemName(body);
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
currentItem.setItemDescription(body);
}
});
try {
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
throw new RuntimeException(e);
}
//return itemStore;
}
Now I am getting exception as
06-30 12:40:45.312: ERROR/AndroidRuntime(315): Uncaught handler: thread main exiting due to uncaught exception
06-30 12:40:45.342: ERROR/AndroidRuntime(315): java.lang.IllegalStateException: This element already has an end text element listener. It cannot have children.
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at android.sax.Element.getChild(Element.java:68)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at android.sax.Element.getChild(Element.java:60)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at org.us.ssg.AndroidSaxFeedParser.parse(AndroidSaxFeedParser.java:82)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at org.us.ssg.DesTestDemoActivity.checkXml(DesTestDemoActivity.java:109)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at org.us.ssg.DesTestDemoActivity.onClick(DesTestDemoActivity.java:81)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at android.view.View.performClick(View.java:2364)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at android.view.View.onTouchEvent(View.java:4179)
06-30 12:40:45.342: ERROR/AndroidRuntime(315): at android.widget.TextView.onTouchEvent(TextView.java:6541)
What I need
I need to read all items (with pos, name and description) and section. I am taking a HashMap, as key I am putting section and as value of that key I am puting an ArrayList of all items (with pos, name, description) related to that particular key (as section name).
You are well on your way. Next step is:
Define a startElementListener for you item element.
Like this:
item.setStartElementListener(new StartElementListener() {
#Override
public void start(Attributes attributes) {
myPojoItem = new PojoItem();
}
});
Define a endElementListener for you item element:
Like this:
item.setEndElementListener(new EndElementListener() {
#Override
public void end() {
itemList.add(myPojoItem);
}
});
For each of the children of item do something like the following:
itemName.setEndTextElementListener(new EndTextElementListener() {
#Override
public void end(String body) {
myPojoItem.setName(body);
}
});
finish with:
try {
Xml.parse(myXmlAsFileInputStream, Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
e.printStackTrace();
}
Update: In response to comment by OP, here is how to access attributes of elements:
item.setStartElementListener(new StartElementListener() {
#Override
public void start(Attributes attributes) {
position = attributes.getValue("pos");
}
});
Final solution
From OP : I have done it with these way
AndroidSaxFeedParser.java
.
public class AndroidSaxFeedParser extends BaseFeedParser {
//Store all items with a particular section
ArrayList<ItemPojo> itemList = new ArrayList<ItemPojo>();
//Store all items categorized by section
Map<String, ArrayList<ItemPojo>> itemStore = new HashMap<String, ArrayList<ItemPojo>>(1);
//Single item
ItemPojo currentItem = null;
//Current section name
String sectionName = null;
public AndroidSaxFeedParser() {
super();
}
public Map<String, ArrayList<ItemPojo>> parse() {
RootElement root = new RootElement(SECTIONS);
Element section = root.getChild(SECTION);
Element itemHeader = section.getChild(ITEM_HEADER);
//Read <name> tag as used as section
itemHeader.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
sectionName = body.trim();
Log.i("New Section", "New section found : " + sectionName);
}
});
section.setStartElementListener(new StartElementListener() {
public void start(Attributes attributes) {
//Clear the item list
itemList = new ArrayList<ItemPojo>(0);
Log.i("Size of list", "Size : " +itemList.size());
}
});
section.setEndElementListener(new EndElementListener() {
public void end() {
//Putting it into master list
itemStore.put(sectionName, itemList);
}
});
Element items = section.getChild(ITEMS);
Element item = items.getChild(ITEM);
items.setEndElementListener(new EndElementListener() {
public void end() {
//sort item with position
Collections.sort(itemList, ItemPojo.COMPARE_BY_POSITION);
}
});
item.setStartElementListener(new StartElementListener() {
public void start(Attributes attributes) {
currentItem = new ItemPojo();
currentItem.setItemPosition(Integer.parseInt(attributes.getValue("pos")));
//Log.i("Test xml", "item initalised " + currentItem.toString());
}
});
item.setEndElementListener(new EndElementListener() {
public void end() {
itemList.add(currentItem);
Log.i("Test xml", "New items found " + currentItem.toString());
}
});
item.getChild(ITEM_NAME).setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
currentItem.setItemName(body.trim());
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
currentItem.setItemDescription(body.trim());
}
});
try {
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
throw new RuntimeException(e);
}
return itemStore;
}
}
.
public abstract class BaseFeedParser implements FeedParser {
// names of the XML tags
static final String SECTIONS = "sections";
static final String SECTION = "section";
static final String ITEM_HEADER = "name";
static final String DESCRIPTION = "description";
static final String ITEM_NAME = "name";
static final String ITEM_POSITION = "pos";
static final String ITEM = "item";
static final String ITEMS = "items";
public InputStream inStream;
public BaseFeedParser() {
//super();
}
protected InputStream getInputStream() {
//Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(DesTestDemoActivity.INDEX_URL);
HttpResponse response = null;
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("request_for", "xml_data"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null)
inStream = entity.getContent();
return inStream;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
.
public interface FeedParser {
Map<String, ArrayList<ItemPojo>> parse();
}
I have done with the help of you guys. So thank you all.
You don't seem to be using a SAX parser here but doing a DOM traveral.
If you want to parse the XML with a SAX parser, you need to initialize a SAXParser and define a ContentHandler where you will implement your parsing logic.
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
/** Send URL to parse XML Tags */
URL sourceUrl = new URL(xmlFile);
/** Create handler to handle XML Tags ( extends DefaultHandler ) */
MyXMLHandler myXMLHandler = new MyXMLHandler();
xr.setContentHandler(myXMLHandler);
xr.parse(new InputSource(sourceUrl.openStream()));
The ContentHandler has callbacks for when the parser reaches a start and end element. There you can put the logic required to fill up your POJO.
In your particular case, you need to check for the item tag and start filling up your POJOs.
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyXMLHandler extends DefaultHandler {
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (localName.equals("sometag")) {
// process tag
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// handle end element
}
}
There are several articles on the web with full code samples for this. Just google for Android and SAX Parser.
One example where an XML file (containing item elements) is parsed using SAX can be found here.

Categories