2010-11-17 82 views
0

我需要帮助:D。我使用的返回类似于XML文件下面的一个Web服务:使用不同元素名称的Android 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上削减这种文档吗?

感谢, marqs

编辑:

我的问题是,< <>图书的子元素>标签强麦号(项目1,项目2,项目3等),所以我不能确定他们。这不会是一个问题,如果“图书”标签将只“项目”的孩子 - 这样的话,我可以使用SAX解析器,并获取“项目”列表

+0

我不明白你的问题,你能详细解释一下吗? – blindstuff 2010-11-17 16:45:33

+0

对不起,我想解析XML文档(上面的那个)此刻我正在使用SAX解析器,但那不起作用,因为当我识别元素时:Element item = books.getChild(“item”)null返回 - 因为XML文档没有'item'标签,但'item1','item2','item3'... – Marqs 2010-11-17 17:28:21

回答

1

是你所描述听起来不那么难的问题:如果您可以放心地假设这些书元素的每一个孩子都是一个“项目”,然后就可以调用你的“项目处理程序”为每个孩子。

下面是伪代码(我认为)会工作,假设<书>总是只有文档的顶级元素:

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

即使伪代码,这是过于简单和丑陋。另一种方法,但可能会因您的需要而被夸大的方法是将您的应用程序分解为多个类,在您到达某些元素的开始或结束时传递责任。

例如:让我们假设一个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); 
     } 
    } 
} 

该方案提供了更多的灵活性和更多的重用可能性。例如,潜在的“书籍”元素现在可以是其他元素的子元素,例如“部门”,而不需要对这些类进行任何更改。

伪代码不是完美无缺的。 (一方面,我想更多地考虑处理程序关闭的位置 - 在父类或孩子中。另一方面,我可能已经过度地将节点引用给父母和孩子这些课程)。但我希望它能给你提供一些你可以开始使用的想法。

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

+0

等等,对不起,我看到你的问题。这是元素的编号。 – ElDog 2010-11-17 16:55:00

0

这似乎是一个很奇怪的XML格式,不可能写出了架构。我假设你无法控制它?这样做会更有意义。

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

使用SAX解析器,在您的处理程序中,您只需查找包含项目的元素名称,而不是与项目完全相同。喜欢的东西:

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

Perfext!它现在有效!谢谢 – Marqs 2010-11-18 11:06:01