【问题标题】:Parsing an XML file in Java to get a list of names在 Java 中解析 XML 文件以获取名称列表
【发布时间】:2011-02-04 05:53:12
【问题描述】:

我目前正在开发一个 Android 应用程序,这意味着要学习 Java。我已经用 Python 玩了几年了,但我决定是时候加强了,因为我有一部 Android 手机。该应用程序基本上显示存储在本地 XML 文件中的视频游戏列表。现在,XML 文件的结构基本上是游戏>游戏(多个)>名称(加上其他现在不重要的东西)。我目前正在尝试获取游戏名称列表。我查找了教程和信息,但似乎都不是我所需要的。我想真正了解它是如何工作的,而不仅仅是有一段我可以复制/粘贴的工作代码。另外,请记住,名称列表必须以字符串数组的形式结束,以便 Android 使用它。这是我现在拥有的功能(从教程复制/粘贴并经过大量编辑,因此不可读。一旦它实际工作,我将修复它。)现在列表视图显示为空。至少它比以前更好,而且它不再崩溃了......

public static String[] parse(String filename) {
      ArrayList<String> gamesList = new ArrayList<String>();

      try {
      File file = new File(filename);
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(file);
      doc.getDocumentElement().normalize();
      NodeList nodeList = doc.getElementsByTagName("game");

      for (int s = 0; s < nodeList.getLength(); s++) {

        Node fstNode = nodeList.item(s);

        //if (fstNode.getNodeType() == Node.ELEMENT_NODE) {

          Element name = (Element) fstNode;
               Element fstElmnt = (Element) fstNode;
          NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("name");
          Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
          NodeList fstNm = fstNmElmnt.getChildNodes();

          gamesList.add(fstNmElmnt.toString());
        //}

      }
      } catch (Exception e) {
        e.printStackTrace();
      }
    String[] gamesArray;
    gamesArray = (String[]) gamesList.toArray(new String[0]);
    return gamesArray;
     }

【问题讨论】:

  • 如果您不熟悉 Java,我不建议您从尝试解析 XML 文件开始。 DOM 调用的一般格式看起来没问题。你在用NodeList nodeList 做什么?程序是否进入 FOR 循环?
  • 除非这是一个学习练习,否则您真的不想玩弄低级 DOM 接口来做可以通过单个 XPath 表达式轻松实现的事情。 (即使您想使用低级树形导航,DOM 也是最糟糕的选择 - JDOM 和 XOM 更容易使用且速度更快。)
  • 其实Android没有XPath。所以我必须做低级的。
  • FYI 看起来较新版本的 Android(Android 2.2 / 8 级)确实支持 XPATH:developer.android.com/reference/javax/xml/xpath/…,对于旧版本,可以使用 dom4j 和 jaxen:brainflush.wordpress.com/2009/05/19/…

标签: java android xml xml-parsing


【解决方案1】:

在您的代码中,在将 fstNmElmnt.toString() 添加到 gameList 时,它是与游戏标签对应的 Element。假设您的 XML 是结构化的 Joe,那么您需要获取第一个孩子的值(而不是为 Element 本身调用 toString()):

gamesList.add(fstNmElmnt.getFirstChild().getNodeValue());

顺便说一句,除非你在文档的其他部分有 标签,或者在这个阶段需要 元素进行其他处理,你可以使用以下(更简单的)代码:

NodeList nodeList = doc.getElementsByTagName("name");
for (int s = 0; s < nodeList.getLength(); ++s) {
    gamesList.add(nodeList.item(s).getFirstChild().getNodeValue());
}

【讨论】:

    【解决方案2】:

    尝试使用Simple :)

    【讨论】:

      【解决方案3】:

      Robert Massaioli's answer 提供有关使用 Simple 的见解。

      要记住的重要一点是,简单 XML 应该能够遵循您可以使用类在逻辑上生成的任何结构。因此,您可以创建一个使用错误接口并应用装饰器模式的 BaseClass,以便将所有这些传递给具体的错误类,而无需任何实现对象知道它们已经给出了什么。

      这可能没有任何意义。不如我给你看一下……好吧……我刚刚离开并实现了我的想法,结果如下(完整代码链接):

      主文件:

      包 com.massaiolir.simple.iface;

      导入 java.io.File;

      导入 org.simpleframework.xml.Serializer; 导入 org.simpleframework.xml.core.Persister;

      公共类主要{ 公共静态 void main(String[] args) 抛出异常 { 序列化器 serial = new Persister(); ResC resc = serial.read(ResC.class, new File("data/testdata.xml"));

          System.out.println(" == Printing out all of the error text. == ");
          System.out.println(resc.getErrorText());
          System.out.println(resc.conRes.getErrorText());
          System.out.println(resc.conRes.conList.getErrorText());
          for (Con con : resc.conRes.conList.cons) {
              System.out.println(con.getErrorText());
          }
          System.out.println(" == Finished printing out all of the error text. == ");
      }
      

      } 它只是简单地运行并显示结果。

      BaseObject.java 类:

      包 com.massaiolir.simple.iface;

      导入 org.simpleframework.xml.Element;

      公共类 BaseObject 实现错误 { @Element(name = "Err", required = false, type = ConcreteError.class) 私人错误err;

      @Override
      public String getErrorText() {
          return err.getErrorText();
      }
      
      @Override
      public void setErrorText(String errorText) {
          err.setErrorText(errorText);
      }
      

      } 如果它想要'Err',这是所有东西都应该扩展的类。

      错误界面:

      包 com.massaiolir.simple.iface;

      公共接口错误{ void setErrorText(String errorText);

      String getErrorText();
      

      } 具体错误类:

      包 com.massaiolir.simple.iface;

      导入 org.simpleframework.xml.Attribute;

      公共类 ConcreteError 实现错误 { @属性 私有字符串文本;

      @Override
      public String getErrorText() {
          return text;
      }
      
      @Override
      public void setErrorText(String errorText) {
          this.text = errorText;
      }
      

      } 实际的实现类在这一点之后。您会发现它们相当琐碎,因为真正的工作是在上面的类中处理的。

      Con 类:

      包 com.massaiolir.simple.iface;

      公共类 Con 扩展 BaseObject {

      } ConList 类:

      包 com.massaiolir.simple.iface;

      导入 java.util.ArrayList;

      导入 org.simpleframework.xml.ElementList;

      公共类 ConList 扩展 BaseObject { @ElementList(entry = "Con", inline = true) 公共 ArrayList 缺点; } ConRes 类:

      包 com.massaiolir.simple.iface;

      导入 org.simpleframework.xml.Element;

      公共类 ConRes 扩展 BaseObject { @Element(name = "ConList") 公共ConList conList; } ResC 类:

      包 com.massaiolir.simple.iface;

      导入 org.simpleframework.xml.Element; 导入 org.simpleframework.xml.Root;

      @Root 公共类 ResC 扩展 BaseObject { @Element(name = "ConRes") 公共ConRes conRes; } 这就是它的全部。很简单吧。我能够在十分钟内完成所有工作。实际上,我写这个回复比我写给你的代码花的时间更长。如果您对我刚刚编写的代码一无所知,请告诉我。我希望这可以帮助您了解如何去做这样的事情。

      【讨论】:

        猜你喜欢
        • 2018-04-05
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2020-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-20
        相关资源
        最近更新 更多