简体   繁体   中英

Trouble with xml parsing through JAVA

I am trying to parse xml through JAVA but after parsing I get org.apache.harmony.xml.dom.DocumentImpl@418b4c98 .

Here is the XML what I am tring to parse, for example, i need id data is 5 and default_image is https://www.10ngah.com/api/images/products/5/5

Xml

<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<products>
<product>
<id>
<![CDATA[ 5 ]]>
</id>
<id_default_image xlink:href="https://www.10ngah.com/api/images/products/5/5"not_filterable="true">
<![CDATA[ 5 ]]>
</id_default_image>
<price>
<![CDATA[ 525 ]]>
</price>
<name>
<language id="1" xlink:href="https://www.10ngah.com/api/languages/1">
<![CDATA[ iPad 2 GB with Cellular ]]>
</language>
</name>
</product>
<product>
<id>
<![CDATA[ 6 ]]>
 </id>
<id_default_image xlink:href="https://www.10ngah.com/api/images/products/6/6" not_filterable="true">
<![CDATA[ 6 ]]>
</id_default_image>
<price>
<![CDATA[ 525 ]]>
</price>
<name>
<language id="1" xlink:href="https://www.10ngah.com/api/languages/1">
<![CDATA[ iPad 2 GB with Cellular ]]>
</language>
</name>
</product>
</products>
</prestashop>

Parsing code

package com.prestoshop.xmlparser;

import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import android.app.Activity;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.BaseAdapter;
import android.widget.Toast;
import com.prestoshop.beans.ProductItems;
import com.prestoshop.utils.Utils;

public class ProductLoaderTask extends AsyncTask<Void, ProductItems, Void> {

private Activity mContext;
private List<ProductItems> products;
private BaseAdapter adapter;

public ProductLoaderTask(Activity context, List<ProductItems> productList,
        BaseAdapter adapter) {
    mContext = context;
    products = productList;
    this.adapter = adapter;
}

static final String KEY_PRESTASHOP = "prestashop";
static final String KEY_ALL_PRODUCTS = "products";

@Override
protected Void doInBackground(Void... params) {

    String url = Utils.PRODUCTS_URL;// use varargs just like an array
    Log.e("urlll", "" + url);
    XMLParser parser = new XMLParser();
    String xml = parser.getXmlFromUrl(url);
    Log.e("string xml", "" + xml);
    Document doc = parser.getDomElement(xml, mContext);


    NodeList nl = doc.getElementsByTagName("product");
            Log.e("noddd",""+nl);
    for (int i = 0; i < nl.getLength(); i++) {
        Element e = (Element) nl.item(i);
        Log.e("eeee", "" + e.toString());
        Log.e("nodelist", ""
                + parser.getValue(e, "price").toString());

        publishProgress(new ProductItems(
                parser.getValue(e, "name"),
                parser.getValue(e, "id"), parser.getValue(e,
                        "id_default_image"), 12.050000));

    }

    return null;
}

@Override
protected void onProgressUpdate(ProductItems... values) {

    ProductItems product = values[0];
    products.add(product);
    adapter.notifyDataSetChanged();
}

@Override
protected void onPostExecute(Void result) {
    Log.e("All done", products.toString());
    super.onPostExecute(result);
 }
}

First your example has syntax error (missing space before attribute)...

I like a JAXB very much... so I would recomend it to you. If your data has static format (not change format in time) it is the best way. Only "problem" could be with CDATA blocks, see this post for more information. Here is "fast" example... it is not nice code just a example!



    public class AdapterCDATA extends XmlAdapter {


      @Override
      public String marshal(String arg0) throws Exception {
        return "";
      }

      @Override
      public String unmarshal(String arg0) throws Exception {
        return arg0;
      }
    }



    public class TestData {

      @XmlRootElement(name = "prestashop")
      @XmlAccessorType(XmlAccessType.FIELD)
      static class Prestashop {

        @XmlElementWrapper(name = "products")
        @XmlElement(name = "product")
        List products;
      }

      @XmlAccessorType(XmlAccessType.FIELD)
      static class Product {
        @XmlJavaTypeAdapter(AdapterCDATA.class)
        @XmlElement(name = "id")
        String id;

        @XmlElement(name = "id_default_image")
        IdDefaultImage idDefaultImage;

        @XmlJavaTypeAdapter(AdapterCDATA.class)
        @XmlElement(name = "price")
        String price;

        @XmlElement(name = "name")
        Name name;
      }

      @XmlAccessorType(XmlAccessType.FIELD)
      static class IdDefaultImage {
        @XmlAttribute(name = "not_filterable")
        String notFilterable;

        @XmlAttribute(name = "href", namespace = "http://www.w3.org/1999/xlink")
        String href;

        @XmlJavaTypeAdapter(AdapterCDATA.class)
        @XmlValue
        String idDefaultImage;
      }

      @XmlAccessorType(XmlAccessType.FIELD)
      static class Name {
        @XmlElement(name = "language")
        Language language;
      }

      @XmlAccessorType(XmlAccessType.FIELD)
      static class Language {
        @XmlJavaTypeAdapter(AdapterCDATA.class)
        @XmlValue
        String language;

        @XmlAttribute(name = "href", namespace = "http://www.w3.org/1999/xlink")
        String href;

        @XmlAttribute(name = "id")
        String id;
      }

      public static void main(String[] args) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(Prestashop.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/test/resources/testData.xml");
        Prestashop prestashop = (Prestashop) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(prestashop, System.out);
      }
    }

Using XmlPullParser following the docs http://developer.android.com/training/basics/network-ops/xml.html

Copied xml to assests folder to parser locally ( for testing only ). You can get the xml from the url and parse.

 InputStream is = MainActivity.this.getResources()
                     .getAssets().open("xmlparser.xml");
               new parserPull(is);

Then to parse

public class parserPull
{

    private static final String ns = null;
    public parserPull(InputStream open) {
        try
        {
             XmlPullParser parser = Xml.newPullParser();
             parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
             parser.setInput(open, null);
             parser.nextTag();
             List<Entry> all = readFeed(parser);
             for(int i=0;i<all.size();i++)
             {
             Log.i("ID is..........",all.get(i).id);
             Log.i("Link is........",all.get(i).link);
             Log.i("Price is.......",all.get(i).price);
             }
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
         List<Entry> entry = null;
        parser.require(XmlPullParser.START_TAG, ns, "prestashop");
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String name = parser.getName();
            //Log.i("..................",name);
            // Starts by looking for the prestashop tag
            if (name.equals("products")) {
              entry= readProducts(parser);
            } else {
                skip(parser);
            }
        }  
        return entry;
    }
    private List<Entry> readProducts(XmlPullParser parser) throws XmlPullParserException, IOException {
        List<Entry> entries = new ArrayList<Entry>();

        parser.require(XmlPullParser.START_TAG, ns, "products");
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String name = parser.getName();
           // Log.i("..................",name);
            // Starts by looking for the products tag
            if (name.equals("product")) {
                entries.add(readEntry(parser));
            } else {
                skip(parser);
            }
        }  
        return entries;
    }
    private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {
        parser.require(XmlPullParser.START_TAG, ns, "product");
        String title = null;
        String summary = null;
        String link = null;
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String name = parser.getName();
           // Log.i("...................",name);
            if (name.equals("id")) {
                title = readId(parser);
            } else if (name.equals("id_default_image")) {
                summary = readLink(parser);
            } else if (name.equals("price")) {
                link = readPrice(parser);
            } else {
                skip(parser);
            }
        }
        return new Entry(title, summary, link);
    }
    private String readPrice(XmlPullParser parser) throws IOException, XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, ns, "price");
        String summary = readText(parser);
        parser.require(XmlPullParser.END_TAG, ns, "price");
        return summary;
    }
    private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException {
        String link = "";
        parser.require(XmlPullParser.START_TAG, ns, "id_default_image");
        String tag = parser.getName();
       // Log.i("............",tag);
        String relType = parser.getAttributeValue(null, "not_filterable");  
        if (tag.equals("id_default_image")) {
            if (relType.equals("true")){
                link = parser.getAttributeValue(null, "xlink:href");
                parser.nextTag();
            } 
        }
        parser.require(XmlPullParser.END_TAG, ns, "id_default_image");
        return link;
    }
    private String readId(XmlPullParser parser) throws IOException, XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, ns, "id");
        String title = readText(parser);
        parser.require(XmlPullParser.END_TAG, ns, "id");
        return title;
    }
    private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
        String result = "";
        if (parser.next() == XmlPullParser.TEXT) {
            result = parser.getText();
            parser.nextTag();
        }
        return result;
    }
    private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            throw new IllegalStateException();
        }
        int depth = 1;
        while (depth != 0) {
            switch (parser.next()) {
            case XmlPullParser.END_TAG:
                depth--;
                break;
            case XmlPullParser.START_TAG:
                depth++;
                break;
            }
        }
     }
    public static class Entry {
        public final String id;
        public final String link;
        public final String price;

        private Entry(String id, String link, String price) {
            this.id = id;
            this.link = link;
            this.price = price;
        }
    }
} 

The log output

12-10 03:29:44.664: I/ID is..........(1511):  5 
12-10 03:29:44.664: I/Link is........(1511): https://www.10ngah.com/api/images/products/5/5
12-10 03:29:44.674: I/Price is.......(1511):  525 
12-10 03:29:44.674: I/ID is..........(1511):  6 
12-10 03:29:44.674: I/Link is........(1511): https://www.10ngah.com/api/images/products/6/6
12-10 03:29:44.674: I/Price is.......(1511):  525 

EXAMPLE XML:

<a>
<b category='3' number='25' points='2'>
<c>
<d filename='' content='some content'/>
<d filename='0134.jpg'/>
</c>
<e>
<f description='desc' correct='1'/>
</e>
</a>

CODE FOR PARSING
Fields in parsing class to make later modification easier:

//data to parse
private static final String TAG_A = "a";        //root

private static final String TAG_B = "b";
private static final String ATT_CATEGORY = "category";
private static final String ATT_POINTS = "points";

private static final String TAG_D = "d";
private static final String ATT_FILE_NAME = "filename";
private static final String ATT_CONTENT = "content";

private static final String TAG_F = "f";
private static final String ATT_DESCRIPTION = "description";
private static final String ATT_CORRECT = "correct";

Method in parsing class:

    private void parseXml()
    {
        try
        {
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(questionsXmlFile, null);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, TAG_A);
            while (parser.next() != XmlPullParser.END_DOCUMENT)
            {
                if (parser.getEventType() == XmlPullParser.START_TAG)
                {
                    String name = parser.getName();
                    if (name.equalsIgnoreCase(TAG_B))
                    {
                        parser.getAttributeValue(null, ATT_CATEGORY));
                        parser.getAttributeValue(null, ATT_POINTS));
                    }
                    else if (name.equalsIgnoreCase(TAG_D))
                    {
                        parser.getAttributeValue(null, ATT_CONTENT));
                        parser.getAttributeValue(null, ATT_FILE_NAME));
                    }
                    else if (name.equalsIgnoreCase(TAG_ANSWER))
                    {
                    }
                }
            }
        }
        catch (XmlPullParserException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

What this method does? It traverse through xml from beginning to END_DOCUMENT and check if tags has been found are interesting one. If yes, check desired attributes and do nothing with it (add your own actions.
Remember, getAttributeValue() can return null. Be sure you dont operate on null .
Remember, parser.require(XmlPullParser.START_TAG, null, TAG_A) returns exception if variables passed to it are wrong comparing current situation of parser.

Your code looks all ok, only you have to remove <![CDATA[ .... ]]>

<id><![CDATA[ 526 ]]></id> change to <id>526</id>

or if you do not want to remove it, then do it following way,

Add the following method/function:

public String getCDataValue(Element e, String id) {
        NodeList title = e.getElementsByTagName(id);
        Element ex = (Element) title.item(0);
        Node child = ex.getFirstChild();
        if (child instanceof CharacterData) {
            CharacterData cd = (CharacterData) child;
            return cd.getData().trim();
        }
        return "";
}

and then use it this way:

NodeList nl = doc.getElementsByTagName("product");
       for (int i = 0; i < nl.getLength(); i++) {
        Element e = (Element) nl.item(i);
        Toast.makeText(getApplicationContext(), getCDataValue(e, "price"),
        Toast.LENGTH_SHORT).show();
}

if its is your code :

publishProgress(new ProductItems(
                      getCDataValue(e, "name"),
                      getCDataValue(e, "id"),
                      getCDataValue(e, "id_default_image"),
                      12.050000)
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM