Проблема парсинга XML в Android с использованием android.sax - PullRequest
0 голосов
/ 29 июня 2011

У меня есть XML-файл как

<?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>

Я определил POJO как

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;
    }
}

Я реализую метод парсинга xml-файла, но не знаю, как мне прочитать несколько тегов <item>, которые находятся внутри тега <items>.

1012 * Отредактированный *

Я помещаю часть кода, который я пытаюсь

//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;
}

Теперь я получаю исключение как

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)

Что мне нужно

Мне нужно прочитать все пункты (с поз, именем и описанием) и раздел. Я использую HashMap, в качестве ключа я помещаю раздел и в качестве значения этого ключа я помещаю ArrayList всех элементов (с pos, именем, описанием), связанных с этим конкретным ключом (как имя раздела).

Ответы [ 2 ]

2 голосов
/ 29 июня 2011

Вы уже в пути.Следующий шаг:

  1. Определите startElementListener для вашего элемента item.Как это:

    item.setStartElementListener(new StartElementListener() {          
                @Override
                public void start(Attributes attributes) {
                    myPojoItem = new PojoItem();
                }
            });
  2. Определить endElementListener для вас элемент элемента: Как это:

    item.setEndElementListener(new EndElementListener() {
                @Override
                public void end() {
                    itemList.add(myPojoItem);
                }
            });
  3. Для каждого из потомковЧтобы сделать что-то вроде следующего:

    itemName.setEndTextElementListener(new EndTextElementListener() {
                @Override
                public void end(String body) {
                                   myPojoItem.setName(body);
                }
            });
  4. закончите с:

    try {
                Xml.parse(myXmlAsFileInputStream, Xml.Encoding.UTF_8, root.getContentHandler());
            } catch (Exception e) {
                e.printStackTrace();
            }

Обновление: в ответ на комментарий OP здеськак получить доступ к атрибутам элементов:

item.setStartElementListener(new StartElementListener() {
    @Override
    public void start(Attributes attributes) {
        position = attributes.getValue("pos");
    }
});

Окончательное решение

Из OP: Я сделал это следующим образом

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();
}

Я сделал с помощью васребята.Так что спасибо всем.

1 голос
/ 29 июня 2011

Похоже, вы здесь не используете SAX-парсер, но выполняете DOM-путешественник.

Если вы хотите проанализировать XML с помощью синтаксического анализатора SAX, вам нужно инициализировать SAXParser и определить ContentHandler, в котором вы будете реализовывать свою логику синтаксического анализа.

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()));

ContentHandler имеет обратные вызовы, когда синтаксический анализатор достигает начального и конечного элементов. Там вы можете поместить логику, необходимую для заполнения вашего POJO.

В вашем конкретном случае вам нужно проверить тег предмета и начать заполнять свои POJO.

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
}
}

В Интернете есть несколько статей с полными примерами кода для этого. Просто Google для Android и SAX Parser.

Один пример, где файл XML (содержащий элементы элемента) анализируется с использованием SAX, можно найти здесь .

...