【问题标题】:Android - XML parsing - working on emulator but not on deviceAndroid - XML解析 - 在模拟器上工作但不在设备上
【发布时间】:2011-05-05 17:34:49
【问题描述】:

在我的应用程序中,我正在解析一个 xml,这是一个结构问题:

<answers>
    <answer value="A">A</answer>
    <answer value="B">B</answer>
    <answer value="C">C</answer>
</answers>

我正在用 XML DOM 解析它:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();

效果很好,根据答案项目,我正在创建这样的 RadioButtons:

NodeList answers = doc.getElementsByTagName("answers").item(0).getChildNodes();

int j = 0;
RadioGroup group = new RadioGroup(this);
RadioButton button1 = new RadioButton(this);
button1.setId((i+1)*100+(j++));
button1.setText(answers.item(1).getChildNodes().item(0).getNodeValue());
button1.setTextColor(Color.BLACK);

RadioButton button2 = new RadioButton(this);
button2.setId((i+1)*100+(j++));
button2.setText(answers.item(2).getChildNodes().item(0).getNodeValue());
button2.setTextColor(Color.BLACK);

RadioButton button3 = new RadioButton(this);
button3.setId((i+1)*100+(j));
button3.setText(answers.item(3).getChildNodes().item(0).getNodeValue());
button3.setTextColor(Color.BLACK);

这段代码在模拟器 SDK v.7 (Android 2.0) 中完美运行,而我的 HTC Desire 在 Android 2.1u1 (so SDK v.8) 上运行

但在设备中,我在这条线上出现错误 button2.setText(answers.item(2).getChildNodes().item(0).getNodeValue()); 猜测答案中没有 .item(2) - 但它必须是......我在模拟器中调试这段代码,发现 answers.item(0)TextNode 包含 XML 节点“answers”的名称...

但确实我有点困惑,在解析这个 XML 时一切都搞砸了,因为我仍然需要计算我有多深以及何时调用哪个元素(节点)上的索引......但我仍然发现这个实现比使用SAX简单得多...

Java 中的 PHP 有没有类似于 SimpleXml 的东西???

无论如何,我的主要问题是:应用程序如何在模拟器中完美运行,而在设备上它会在我尝试为 button2 设置文本的行抛出 NullPointerException

非常感谢您的帮助!!!

【问题讨论】:

  • 哦,当我直接在devicem上输出setText()值时,button1.setText(answers.item(1).getChildNodes().item(0).getNodeValue());被正确处理并且输出了值,而下一项button2.setText(answers.item(2).getChildNodes().item(0).getNodeValue());抛出了一个错误...所以我完全不明白...
  • 我的建议:在 Android 中停止使用文档生成器来解析 XML,改用简单库 (simple.sourceforge.net),这里有一篇关于它的博客文章 (massaioli.homelinux.com/wordpress/2011/04/21/…)
  • @RobertMassaioli:嗯,我看过了,它看起来不错,但仍然不是很简单-您必须为 XML 中的每个“对象”编写和定义一个类(因此对于每个标签)-哪里有简化???是的,也许在解析 XML 时,它更简单,但是您必须生成可能多两倍的代码......但是 - 我会在有时间的时候尝试一下......
  • @shadyyx 这不是真的,你不需要为每个标签写一个类。看看 Simple 中的路径注解,它允许您使用 XPath 表达式映射多个嵌套的 XML 元素和属性。

标签: android xml dom xml-parsing


【解决方案1】:

getChildNodes() 返回答案下的所有Nodes,而不仅仅是所有Elements。您可能想要遍历所有子项并检查每个子项是否是标签名称为“answer”的Element

这样的事情怎么样:

NodeList answers = doc.getElementsByTagName("answer");
for (int x = 0; x < answers.getLength(); x++) {
  Node answer = answers.get(x);
  // you could do some checking here, make sure Node is instanceof Element, etc.
  RadioButton radioButton = new RadioButton(this);
  radioButton.setId((i+1)*100+(x));
  radioButton.setText(node.getNodeValue());
  radioButton.setTextColor(Color.BLACK);
  // add the radio button to some view
}

这样您就不会依赖特定数量的答案子元素,并且您保证不会尝试访问不存在的子元素。

如果你真的想根据 Answers 节点的子节点来做,

Node answersNode = // get the node
NodeList childNodes = answersNode.getChildNodes();
for (int x = 0; x < childNodes.getLength(); x++) {
  Node node = childNodes.get(0);
  if (node instanceof Element && node.getNodeName().equals("answer")) {
    // do the same as above to create a radio button.
  }
}

【讨论】:

  • “这样您就不会依赖于特定数量的答案子元素,并且您保证不会尝试访问不存在的子元素。” - 这是真的,我知道这个解决方案,但每个答案元素中总是只有三个答案元素,所以我知道只有三个 RadioButtons 必须创建。无论如何,感谢您的帮助,特别是检查标签名称的部分 - 这从来没有出现在我的脑海中......我以不同的方式解决了问题,问题主要出在 PHP 脚本中...... (在下一条评论中继续)
  • ... 生成 XML - 我使用 \n 分隔生成另一个 TextImpl 节点的行,该节点包含 \n\n\n\n 在模拟器中 不存在(不知何故) 在真实设备中...从 PHP 脚本中删除每个 \n 后,解析在模拟器中的工作方式与在真实设备中相同...我为帖子 +1,但无法将其标记为答案我在其他地方以不同的方式想通了...但是谢谢!!!
  • 这听起来很脆弱。空白不应影响 xml 的解析方式。即使您始终只有 3 个单选按钮,循环遍历仍然比假设它们存在于某个索引处更清晰。
【解决方案2】:

使用(简单 XML)[http://simple.sourceforge.net/]

@Root
public class Answers {

   @ElementMap(entry="answer", key="value" attribute="true" inline=true)
   public Map<String, String> map;
}

或者,如果你只有三个条目,你可以做到。

@Root
public class Answers {

   @Path("answer[1]")
   @Text
   private answerValue1;

   @Path("answer[2]")
   @Text
   private answerValue2;

   @Path("answer[3]")
   @Text
   private answerValue3;

   @Path("answer[1]")
   @Attribute(name="value")
   private answerAttribute1;

   @Path("answer[2]")
   @Attribute(name="value")
   private answerAttribute2;

   @Path("answer[3]")
   @Attribute(name="value")
   private answerAttribute3;
}

然后像这样读。

Persister persister = new Persister();
Answers answers = persister.read(Answers.class, xml);

就这么简单!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-19
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多