在 Java 中解析 XML 文件以获取名称列表

发布于 2024-10-15 20:15:30 字数 1532 浏览 2 评论 0原文

我目前正在开发 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;
     }

I am currently working on an Android app and that means learning Java. I've toyed around with Python for a few years, but decided it was time to step up now that I have an android phone. The app basically displays a list of video games stored in an XML file locally. Right now, the structure of the XML file is basically games>game (Multiple)>name (Plus other things not important now). I am currently trying to get a list of the names of the games. I've looked up tutorials and info but none of it seems to be quite what I need. I want to actually understand how it works, not just have a working piece of code I can copy/paste. Also, keep in mind that the list of names has to end up as an array of strings for Android to use it. Here's the function I have right now (Copy/pasted from a tutorial and heavily edited, so it's not readable. I'll fix that once it's actually working.) Right now the listview shows up as empty. At least it's better than before and it doesn't crash anymore though...

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

铁轨上的流浪者 2024-10-22 20:15:30

在您的代码中,当您将 fstNmElmnt.toString() 添加到 gameList 时,它是与游戏标签对应的元素。假设您的 XML 结构为Joe,那么您需要获取第一个子元素的值(而不是为元素本身调用 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());
}

In your code, at the point that you add fstNmElmnt.toString() to gameList, it is the Element corresponding to the tag of the game. Assuming that your XML is structured <name>Joe</name>, then you need to get the value of the first child (instead of calling toString() for the Element itself):

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

By the way, unless you have <name> tags in other parts of your document, or need the <game> element for other processing at this stage, you can use the following (much simpler) code:

NodeList nodeList = doc.getElementsByTagName("name");
for (int s = 0; s < nodeList.getLength(); ++s) {
    gamesList.add(nodeList.item(s).getFirstChild().getNodeValue());
}
我最亲爱的 2024-10-22 20:15:30

尝试使用 简单 :)

Try using Simple :)

风和你 2024-10-22 20:15:30

Robert Massaioli 的回答提供了有关使用 Simple 的见解。

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

这可能毫无意义。我只是告诉你怎么样...好吧...我刚刚离开并完全实现了我的想法,这里是结果(完整代码链接):

主文件:

package com.massaiolir.simple.iface;

导入java.io.File;

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

公共类主要{
公共静态无效主(字符串[] 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)
私人错误错误;

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

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

}
如果需要“Err”,那么所有东西都应该扩展这个类。

Error接口:

包com.massaiolir.simple.iface;

公共接口错误{
无效 setErrorText(字符串 errorText);

String getErrorText();

}
ConcreteError类:

包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(名称 = "ConList")
公共 ConList conList;
}
ResC类:

包com.massaiolir.simple.iface;

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

@根
公共类 ResC 扩展 BaseObject {
@Element(名称 = "ConRes")
公共 ConRes conRes;
}
这就是全部内容。很简单吧。我能在十分钟内把这一切搞定。实际上,我写这个回复所花费的时间比我编写给您的代码所花费的时间还要长。如果您对我刚刚编写的代码有任何不明白的地方,请告诉我。我希望这可以帮助您了解如何去做这样的事情。

Robert Massaioli's answer provides insights into using Simple.

The important thing to remember is that Simple XML should be able to follow any structure that you can logically generate using classes. So you could just create a BaseClass that uses an error interface and applies the Decorator pattern so that it passes all of that through to a concrete error class without any of the implementing objects needing to know what they have been given.

That probably made no sense. How about I just show you...okay...I just went away and implemented exactly what I was thinking and here are the results (full code link):

The Main File:

package com.massaiolir.simple.iface;

import java.io.File;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

public class Main {
public static void main(String[] args) throws Exception {
Serializer 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. == ");
}

}
It just runs simple and displays the results.

The BaseObject.java class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

public class BaseObject implements Error {
@Element(name = "Err", required = false, type = ConcreteError.class)
private Error err;

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

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

}
This is the class that everything should extend if it wants 'Err'.

The Error interface:

package com.massaiolir.simple.iface;

public interface Error {
void setErrorText(String errorText);

String getErrorText();

}
The ConcreteError class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Attribute;

public class ConcreteError implements Error {
@Attribute
private String text;

@Override
public String getErrorText() {
    return text;
}

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

}
The actual implementing classes are after this point. You will see that they are rather trivial because the real work is being handled in the classes above.

The Con class:

package com.massaiolir.simple.iface;

public class Con extends BaseObject {

}
The ConList class:

package com.massaiolir.simple.iface;

import java.util.ArrayList;

import org.simpleframework.xml.ElementList;

public class ConList extends BaseObject {
@ElementList(entry = "Con", inline = true)
public ArrayList cons;
}
The ConRes class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

public class ConRes extends BaseObject {
@Element(name = "ConList")
public ConList conList;
}
The ResC class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root
public class ResC extends BaseObject {
@Element(name = "ConRes")
public ConRes conRes;
}
And that is all that there is to it. Pretty simple right. I was able to bang that all out in ten minutes. It actually took me longer to write this response than it took me to write the code that I am giving you. If you do not understand anything about the code that I have just written then please let me know. I hope this helps you to understand how you might go about doing something like this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文