使用Java解析XML文件以获取名称列表

时间:2022-12-01 13:39:01

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

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

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

3 个解决方案

#1


1  

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):

在您的代码中,在向游戏列表添加fstNmElmnt.toString()时,它是与游戏标记相对应的元素。假设您的XML是结构化的 Joe ,那么您需要获取第一个子节点的值(而不是为Element本身调用toString()):

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

#2


0  

Try using Simple :)

尝试使用简单:)

#3


0  

Robert Massaioli's answer provides insights into using Simple.

Robert Massaioli的回答提供了使用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.

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

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;

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"));

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:

BaseObject.java类:

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;

公共类BaseObject实现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'.

如果它想要'Err',这就是所有应该扩展的类。

The Error interface:

错误界面:

package com.massaiolir.simple.iface;

public interface Error { void setErrorText(String errorText);

public interface Error {void setErrorText(String errorText);

String getErrorText();

} The ConcreteError class:

ConcreteError类:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Attribute;

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

public class ConcreteError实现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:

Con类:

package com.massaiolir.simple.iface;

public class Con extends BaseObject {

公共类Con扩展BaseObject {

} The ConList class:

ConList类:

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:

公共类ConList扩展BaseObject {@ElementList(entry =“Con”,inline = true)public ArrayList cons; ConRes类:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

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

公共类ConRes扩展BaseObject {@Element(name =“ConList”)public ConList conList; ResC类:

package com.massaiolir.simple.iface;

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

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.

@Root公共类ResC扩展了BaseObject {@Element(name =“ConRes”)public ConRes conRes;这就是它的全部内容。非常简单吧。我能在十分钟内全力以赴。编写这个响应实际上花了我更长的时间,而不是我编写我给你的代码。如果您对我刚刚编写的代码一无所知,请告诉我。我希望这有助于你了解如何做这样的事情。

#1


1  

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):

在您的代码中,在向游戏列表添加fstNmElmnt.toString()时,它是与游戏标记相对应的元素。假设您的XML是结构化的 Joe ,那么您需要获取第一个子节点的值(而不是为Element本身调用toString()):

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

#2


0  

Try using Simple :)

尝试使用简单:)

#3


0  

Robert Massaioli's answer provides insights into using Simple.

Robert Massaioli的回答提供了使用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.

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

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;

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"));

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:

BaseObject.java类:

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;

公共类BaseObject实现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'.

如果它想要'Err',这就是所有应该扩展的类。

The Error interface:

错误界面:

package com.massaiolir.simple.iface;

public interface Error { void setErrorText(String errorText);

public interface Error {void setErrorText(String errorText);

String getErrorText();

} The ConcreteError class:

ConcreteError类:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Attribute;

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

public class ConcreteError实现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:

Con类:

package com.massaiolir.simple.iface;

public class Con extends BaseObject {

公共类Con扩展BaseObject {

} The ConList class:

ConList类:

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:

公共类ConList扩展BaseObject {@ElementList(entry =“Con”,inline = true)public ArrayList cons; ConRes类:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

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

公共类ConRes扩展BaseObject {@Element(name =“ConList”)public ConList conList; ResC类:

package com.massaiolir.simple.iface;

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

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.

@Root公共类ResC扩展了BaseObject {@Element(name =“ConRes”)public ConRes conRes;这就是它的全部内容。非常简单吧。我能在十分钟内全力以赴。编写这个响应实际上花了我更长的时间,而不是我编写我给你的代码。如果您对我刚刚编写的代码一无所知,请告诉我。我希望这有助于你了解如何做这样的事情。