JAVA - 解析来自 XML 的特定数据
JAVA - parsing specific data from XML
有很多页面解释 XML,但我还没有找到任何内容来解决我的特定问题。我有一个 XML 文件,它定义了我正在开发的一个简单游戏的所有项目。因为我不想一直加载整个地图,所以我也不需要一直加载游戏中的每个项目。只是我正在使用的地图部分中的那些。我知道 SAX 是最好的方法。基本上我想做的是拥有这样的东西:
<item>
<id>12345</id>
<name>note</name>
<weight>.1</weight>
</item>
<item>
.......
</item>
我想编写一个函数,它可以获取项目 ID 的数组(从另一个特定于我当时正在加载的地图的列表中提取),并为每个给定的 ID 解析 xml 文件,然后当它找到一个项目标签,其 id 标签包含它要查找的 id 时,从该项目中的每个标签中获取数据并将其设置为变量(id、note 和 weight),我可以将其传递给构造函数方法.这样,我只构建相关的项目对象。但我不确定该怎么做。任何帮助将不胜感激。
编辑:
好的,我想我差不多已经弄明白了,但仍然 运行 遇到了问题。这是我的
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 给出 "can't find symbol" 错误。我觉得这是一个简单的范围问题,但我似乎无法解决它。
您无法访问 foundName
,因为它是在 new DefaultHandler() { ... }
内部 class.
中声明的
您可以将 foundName
向上移动两行,在内部 class 之外,但是为了在内部 class 内部访问它,您需要将其 final
,这使得它对你想要的东西毫无用处。
你想要的是类似 handler.foundName
的东西,但是 handler
被声明为 DefaultHandler
类型,它没有名为 foundName
的字段。您的内部 class 确实 具有该字段,但该类型没有类型名。你的问题就在这里。解决办法是把它变成一个成熟的 class:
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 处理有缺陷。您不能保证在对 public void characters(char[] ch, int start, int length)
的一次调用中获得标记 <tag>yada,yada,yada</tag>
之间的所有字符( 请注意正确的签名 )。您应该只累积它们,并在结束标记中处理它们。类似于:
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
}
}
有很多页面解释 XML,但我还没有找到任何内容来解决我的特定问题。我有一个 XML 文件,它定义了我正在开发的一个简单游戏的所有项目。因为我不想一直加载整个地图,所以我也不需要一直加载游戏中的每个项目。只是我正在使用的地图部分中的那些。我知道 SAX 是最好的方法。基本上我想做的是拥有这样的东西:
<item>
<id>12345</id>
<name>note</name>
<weight>.1</weight>
</item>
<item>
.......
</item>
我想编写一个函数,它可以获取项目 ID 的数组(从另一个特定于我当时正在加载的地图的列表中提取),并为每个给定的 ID 解析 xml 文件,然后当它找到一个项目标签,其 id 标签包含它要查找的 id 时,从该项目中的每个标签中获取数据并将其设置为变量(id、note 和 weight),我可以将其传递给构造函数方法.这样,我只构建相关的项目对象。但我不确定该怎么做。任何帮助将不胜感激。
编辑:
好的,我想我差不多已经弄明白了,但仍然 运行 遇到了问题。这是我的
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 给出 "can't find symbol" 错误。我觉得这是一个简单的范围问题,但我似乎无法解决它。
您无法访问 foundName
,因为它是在 new DefaultHandler() { ... }
内部 class.
您可以将 foundName
向上移动两行,在内部 class 之外,但是为了在内部 class 内部访问它,您需要将其 final
,这使得它对你想要的东西毫无用处。
你想要的是类似 handler.foundName
的东西,但是 handler
被声明为 DefaultHandler
类型,它没有名为 foundName
的字段。您的内部 class 确实 具有该字段,但该类型没有类型名。你的问题就在这里。解决办法是把它变成一个成熟的 class:
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 处理有缺陷。您不能保证在对 public void characters(char[] ch, int start, int length)
的一次调用中获得标记 <tag>yada,yada,yada</tag>
之间的所有字符( 请注意正确的签名 )。您应该只累积它们,并在结束标记中处理它们。类似于:
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
}
}