Android XML解析具有不同的元素名称

时间:2010-11-17 16:37:12

标签: android xml parsing sax

我需要帮助:D。我正在使用Web服务返回类似的xml文件到下面的那个:

<books>
<item_1>
    <name></name>
    <type></type>
</item_1>
<item_2>
    <name></name>
    <type></type>
</item_2>
<item_3>
    <name></name>
    <type></type>
</item_3>
...
...</books>

问题是我不知道如何在Android中解析它。如果'books'标签的子元素具有相同的名称(item而不是:item_1,item_2,item_3 ......),那么一切都会好的。然后我可以轻松使用SAX解析器。

你知道我怎么能在Android中削减这种文件吗?

谢谢, 马克斯

编辑:

我的问题是&lt;&lt;&gt; books&gt;的子元素标签啤酒编号(item1,item2,item3等)所以我无法识别它们。如果'books'标签只有'item'子项,这不会有问题 - 所以我可以使用SAX解析器并获取'item'列表

3 个答案:

答案 0 :(得分:1)

你所描述的问题听起来并不那么难:如果你可以放心地假设books元素的每个孩子都是“item”,那么你可以调用你的“item”处理程序“为每个孩子。

这是伪代码(我认为)可行,假设&lt; books&gt;始终只是文档的顶级元素:

class BookHandler extends DefaultHandler {
   public void startElement(String namespaceURI, String localName, 
                String qName, Attributes atts) {
        if (localName.equals("books") {
            // Don't need to do anything with the top level element
            return;
        }
        else {
            handleItem(namespaceURI, localName, qName, atts);
        }
    }

    public void  endElement(String namespaceURI, String localName, String qName) {
         if localName.equals("books") {
            // Stop parsing and exit.
         }
         else {
            // Stop parsing one item
         }
    }

    private void handleItem(String namespaceURI, String localName, 
                 String qName, Attributes atts) {
         // Handle one item, including handling the "name" and 
         // "type" child attributes
         if (localName.equals("name") {
            // handle the name
         }
         else if (localName.equals("type") {
            // handle the type
         }
    }
}

即使是伪代码,这也过于简单和丑陋。另一种方法,但可能过分夸大您的需求,是将您的应用程序分解为多个ContentHandler类,在您到达某些元素的开头或结尾时将责任分开。

例如:假设将BookHandler的一个实例传入parser.parse()调用,以处理顶级元素。然后:

class BookHandler extends DefaultHandler {
   private ContentHandler m_parentHandler;
   private ContentHandler m_childHandler = null;

   // ... == appropriate args for the DefaultHandler constructor
   public BookHandler(ContentHandler parent, Attributes atts, ...) {
        super(...);
        m_parentHandler = parent;
        parent.getXMLReader().setHandler(this);
   }

   public void startElement(String namespaceURI, String localName, 
                String qName, Attributes atts) {
        if (localName.equals("books") {
            // Don't need to do anything with the top level element
            return;
        }
        else {
            // Assume it's a new item element. (Note: ItemHandler's constructor
            // changes the parser's ContentHandler.)
            m_childHandler = new ItemHandler(this, atts, ...);
        }
    }

    public void  endElement(String namespaceURI, String localName, String qName) {
         if localName.equals("books") {
            // Stop parsing and exit.
         }
         else {
            // Note that this won't be called for "item" elements, UNLESS the
            // ItemHandler's endElement method explicitly invokes this method.

            // Stop parsing one item

         }
    }    
}


class ItemHandler extends DefaultHandler {
   private ContentHandler m_parentHandler;

    // ItemInfo is a class that holds all info about the current item
   private ItemInfo m_ItemInfo = null;

   // ... == appropriate args for the DefaultHandler constructor
   public ItemHandler(ContentHandler parent, Attributes atts, ...) {
        super(...);
        m_parentHandler = parent;
        m_ItemInfo = new ItemInfo(atts);
        parent.getXMLReader().setHandler(this);
   }

   public void startElement(String namespaceURI, String localName, 
                String qName, Attributes atts) {
        if (localName.equals("name") {
             // Handle the name. Update the current item as needed.
        }
        else  if (localName.equals("type") {
             // Handle the type. Update the current item as needed.
        }
    }

    public void  endElement(String namespaceURI, String localName, String qName) {
         if localName.equals("name" || localName.equals("type") {
             // Do nothing (?)
         }
         else {
            // Stop parsing the current item; 
            // let the parent class handle the next element.
            getXMLReader().setHandler(m_parentHandler);

            // OPTIONALLY -- depending on your app's needs -- call the
            // parent's endElement() method to let it know that we reached
            // the end of an item.
            m_parentHandler.endElement(namespaceURI, localName, qName);
         }
    }   
}

该方案提供了更大的灵活性和更多的重用可能性。例如,“books”元素现在可能是某些其他元素的子元素,比如“部门”,对这些类没有太大要求。

伪代码无论如何都不完美。 (首先,我想更多地考虑关闭处理程序的位置 - 在父类或孩子中。另一方面,我可能已经过度保存对父母和孩子的引用。这些课程。)但我希望它能为您提供可以开始使用的想法。

答案 1 :(得分:0)

我之前使用过DocumentBuilderFactory

URL connectURL;
InputStream is;
NodeList names;
NodeList types

try
{
  connectURL = new URL("http://example.com/exampleservice");

  try
  {
    URLConnection connection = connectURL.openConnection();
    is = connection.getInputStream();
  } catch (IOException e)
  {
    e.printStackTrace();
  }
} catch (MalformedURLException e1)
{
  e1.printStackTrace();
}

DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
try
{
  DocumentBuilder docBuillder = docBuilderFactory.newDocumentBuilder();
  Document doc = docBuillder.parse(is);
  names = doc.getElementsByTagName("name");
  types = doc.getElementsByTagName("type");
  } catch (ParserConfigurationException e)
  {
    e.printStackTrace();
  } catch (SAXException e)
  {
    e.printStackTrace();
  } catch (IOException e)
  {
    e.printStackTrace();
  }
}

这应该产生NodeLists,它应该包含你想要玩的东西。

谢谢,

ElDog

答案 2 :(得分:0)

这似乎是一种非常奇怪的XML格式,无法为其编写架构。我假设你无法控制它?做一些类似的事情会更有意义。

如果您使用的是dom解析器,则可以在不知道元素名称的情况下遍历元素树。在您的books元素中,只需致电getChildNodes

使用SAX解析器,在您的处理程序中,您只需要查找包含item的元素名称,而不是完全等于item。类似的东西:

 public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
        super.startElement(uri, localName, name, attributes);
        if (localName.contains("item")){
            // create some item object
        }
    }