【问题标题】:XML parsing problem in android using android.saxandroid中使用android.sax的XML解析问题
【发布时间】:2011-09-24 22:54:27
【问题描述】:

我有一个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文件的方法,但我不知道如何读取多个&lt;item&gt;标签,它们在&lt;items&gt;标签内。

已编辑

我正在输入部分代码,我正在尝试

//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。

【问题讨论】:

    标签: java android sax xml-parsing


    【解决方案1】:

    您似乎没有在这里使用 SAX 解析器,而是在执行 DOM 遍历。

    如果你想用 SAX 解析器解析 XML,你需要初始化一个 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。

    可以在here 找到一个使用 SAX 解析 XML 文件(包含项目元素)的示例。

    【讨论】:

    • 你能提供一些关于它的链接吗?这是针对 Android 的吗
    • 查看使用 SAX 的 android 示例的更新答案。该示例是一个 Android 应用程序,但 SAX 解析本身不包含任何 Android 细节。
    【解决方案2】:

    你一切顺利。下一步是:

    1. 为您的项目元素定义一个 startElementListener。 像这样:

      item.setStartElementListener(new StartElementListener() {
                  @覆盖
                  公共无效开始(属性属性){
                      myPojoItem = 新 PojoItem();
                  }
              });
    2. 为您的项目元素定义一个 endElementListener: 像这样:

      item.setEndElementListener(new EndElementListener() {
                  @覆盖
                  公共无效结束(){
                      itemList.add(myPojoItem);
                  }
              });
    3. 对 item 的每个子项执行以下操作:

      itemName.setEndTextElementListener(new EndTextElementListener() {
                  @覆盖
                  公共无效结束(字符串主体){
                                     myPojoItem.setName(body);
                  }
              });
    4. 结束:

      尝试{
                  Xml.parse(myXmlAsFileInputStream, Xml.Encoding.UTF_8, root.getContentHandler());
              } 捕捉(异常 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();
    }
    

    在你们的帮助下我已经完成了。所以谢谢大家。

    【讨论】:

    • 我可以用手来处理这个答案的格式,有没有我可以阅读的指南?
    • 阅读:ibm.com/developerworks/opensource/library/x-android/#N101E0 清单 8 中的示例正是您所需要的
    • @user594955:基本上,每次解析器到达一个新项目时,您都会创建一个新项目,当解析器到达一个项目的末尾时,您将该项目添加到项目列表中。在这期间,解析器将到达项目的所有子元素,您所要做的就是从这些元素中提取数据并将它们存储在 PojoItem 对象中,使用 endElementListener
    • @videre 我正在使用这种方法,但是如何读取 等标签中的值,我想读取 pos 值。
    • @user594955:我现在更新了答案以包括属性值的提取。
    猜你喜欢
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多