有很多页面解释 XML,但我还没有找到任何可以解决我的特定问题的内容。我有一个 XML 文件,定义了我正在开发的一个简单游戏的所有项目。由于我不想始终加载整个 map ,因此我也不需要始终加载游戏中的每个项目。只是我正在处理的 map 部分中的那些。我知道 SAX 是最好的方法。基本上我想做的是有这样的东西:
<item>
<id>12345</id>
<name>note</name>
<weight>.1</weight>
</item>
<item>
.......
</item>
我想编写一个函数,它可以获取一个项目 id 数组(从特定于我当时加载的 map 的另一个列表中提取),并且对于给定的每个 id 通过 xml 文件进行解析,然后当它找到一个项目标签,其 id 标签包含它要查找的 id,从该项目中的每个标签获取数据并将其设置为可以传递给构造函数方法的变量(id、注释和重量)。这样,我只构建相关的项目对象。但我不知道该怎么做。任何帮助将不胜感激。
<小时/>编辑:
好吧,我想我已经解决了这个问题,但仍然遇到了问题。这是我所拥有的
public class SaxParsing {
public static void main(String argv[]) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
String foundName = null;
int idGiven = 101002;
boolean b_id = false;
boolean b_idToFind = false;
boolean b_name = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (localName.equalsIgnoreCase("id")) {
b_id = true;
}
if (localName.equalsIgnoreCase("name")) {
b_name = true;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equalsIgnoreCase("id")) {
b_id = false;
}
if (localName.equalsIgnoreCase("name")) {
b_name = false;
}
if (localName.equalsIgnoreCase("item")) {
b_idToFind = false;
}
}
public void characters(char buffer, int start, int length) throws SAXException {
if (b_id) {
String temp = new String();
temp = String.valueOf(buffer);
if (temp == Integer.toString(idGiven)) {
b_idToFind = true;
}
}
if (b_name) {
if (b_idToFind) {
foundName = new String();
foundName = String.valueOf(buffer);
}
}
}
};
saxParser.parse("path\\to\\GameItems.xml", handler);
System.out.println(foundName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
一切正常,除了我无法访问 DefaultHandler
之外的变量 foundName
。 NetBeans 给出“找不到符号”错误。我觉得这是一个简单的范围问题,但我似乎无法解决它。
最佳答案
您无法访问 foundName
因为它是在 new DefaultHandler() { ... }
内部声明的内部类。
您可以移动foundName
在内部类之外增加两行,但为了在内部类内部访问它,您需要将其设置为 final
,这使得它对你想要的东西毫无用处。
你想要的是类似handler.foundName
的东西,但是handler
被声明为类型 DefaultHandler
,它没有名为 foundName
的字段。您的内部类确实具有该字段,但该类型没有类型名称。这就是你的问题所在。解决方案是将其变成一个成熟的类:
class ItemHandler extends DefaultHandler {
String foundName;
public void startElement(...) {...}
public void endElement(...) {...}
public void characters(...) {...}
}
然后你可以声明handler
类型为ItemHandler
,并获得访问其字段的能力:
ItemHandler handler = new ItemHandler();
saxParser.parse("path\\to\\GameItems.xml", handler);
System.out.println(handler.foundName);
作为旁注。您的 SAX 处理有缺陷。不保证您获得标签 <tag>yada,yada,yada</tag>
之间的所有字符一次调用 public void characters(char[] ch, int start, int length)
(记下正确的签名)。您应该只累积它们,并在结束标记中处理它们。像这样的东西:
class ItemHandler extends DefaultHandler {
int idGiven = 101002;
String foundName = null;
private StringBuilder sb = new StringBuilder();
private String item_name;
private int item_id;
@Override
public void startElement(String uri, String localName, String qName, Attributes attr) {
sb.setLength(0); // Clear the buffer
}
@Override
public void characters(char[] buffer, int start, int length) {
sb.append(buffer, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) {
switch(localName) {
case "id":
item_id = Integer.parseInt(sb.toString());
break;
case "name":
item_name = sb.toString();
break;
case "item":
if (item_id == idGiven) {
foundName = item_name;
}
break;
default:
System.err.println("Unexpected tag: "+localName);
}
sb.setLength(0); // Clear the buffer
}
}
关于JAVA - 从XML解析特定数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37060721/