我正在尝试构建一个简单的程序来将xml文件转换为对象,反之亦然。我试图将标签之间的xml数据存储到一个对象中,然后将该对象存储到另一个类的另一个对象中。问题是,每当我尝试将一些字符串从xml-parses传递给第一个存储对象(例如名称,平台等)时,它们就会丢失它们的值。字符串确实被传递到存储对象,但存储只是来自" XXXXXX"到""。我们的theacer或者我都无法解决这个问题。有什么想法吗?
以下是造成破坏的类。
public class MySaxParser
extends DefaultHandler {
public static int element;
public static String elementit[] = {"name","studio","genre","platform","published"};
public static String Name, Studio, Genre, Platform, Published;
public static OutFile outF = new OutFile();
private static Library Pelit = new Library();
private static Game peli;
public Library getLib(){
return Pelit;
}
public void parse() {
/*if (args.length != 1) {
System.out.println("Usage: java .MySaxParser [URI]");
System.exit(0);
}*/
// oli public static ja metodin ulkopuolella
System.setProperty("javax.xml.parsers.SAXParserFactory",
"org.apache.xerces.jaxp.SAXParserFactoryImpl");
//String uri = args[0];
String uri = "src\\gamelib\\Gamelibrary.xml";
try {
if (outF.askName())
outF.openFile(); // ok, avataan tiedosto
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setValidating(true);
parserFactory.setNamespaceAware(false);
parserFactory.setFeature(
"http://apache.org/xml/features/validation/schema", true);
MySaxParser MySaxParserInstance = new MySaxParser();
SAXParser parser = parserFactory.newSAXParser();
parser.parse(uri, MySaxParserInstance);
}
catch (IOException exception) {
exception.printStackTrace();
}
catch (SAXException exception) {
exception.printStackTrace();
}
catch (ParserConfigurationException exception) {
exception.printStackTrace();
}
catch (FactoryConfigurationError exception) {
exception.printStackTrace();
}
System.out.println("Prasing done.");
}
public void characters(char[] ch, int start, int length) throws SAXException {
String s = new String(ch, start, length);
s = s.trim();
switch(element){
case 1:
peli.setName(s);
break;
case 2:
peli.setStudio(s);
break;
case 3:
peli.setGenre(s);
break;
case 4:
peli.setPlaform(s);
break;
case 5:
peli.setPublished(s);
break;
//outF.write(s); jos halutaan printata tiedostoon nin tämä käyttöön
}
}
public void endDocument() throws SAXException {
}
public void endElement(String url, String localName, String qName) throws
SAXException {
System.out.println("Loppuva elementti: "+qName);
if (qName.equals("game"))
Pelit.AddGame(peli);
}
public void startDocument() throws SAXException {
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("Alkava elementti: "+qName);
switch(qName){
case "name":
element = 1;
break;
case "studio":
element = 2;
break;
case "genre":
element = 3;
break;
case "platform":
element = 4;
break;
case "published":
element = 5;
break;
case "game":
peli = new Game();
break;
}
}
public void fatalError(SAXParseException e) throws SAXException {
throw new java.lang.UnsupportedOperationException(
"Method fatalError() not yet implemented.");
}
和存储类。
public class Game {
private static String Name, Studio, Genre, Plaform, Published;
public String getName() {return Name;}
public String getStudio() {return Studio;}
public String getGenre() {return Genre;}
public String getPlaform() {return Plaform;}
public String getPublished() {return Published;}
public void setName(String Name) {this.Name = Name;}
public void setStudio(String Studio) {this.Studio = Studio;}
public void setGenre(String Genre) {this.Genre = Genre;}
public void setPlaform(String Plaform) {this.Plaform = Plaform;}
public void setPublished(String Published) {this.Published = Published;}
}
我已经多次调试过代码,用它尝试了无法形容的东西,现在我一无所知。
一旦澄清。调试显示peli.setName(s)
确实执行了正确的值 - 让我们说" Derp" - 它确实已注册到Game.Name
,但价值来自" Derp"到""如果我在调试中更进一步。
答案 0 :(得分:1)
我对你的问题并不完全清楚,但我认为这就是问题所在:
解析器正在多次调用您的characters
方法,其中一些方法只包含空格字符或没有字符。
致残:
<foo>
<bar>The Text I Want</bar>
</foo>
在上面的XML中,解析器可以在characters
和</bar>
之间自由调用</foo>
,并且它将包含一些空格(如果格式化XML,则会显示标签和新行)。
在存储从characters
检索到的信息之前,您应该验证您是否在正确的元素中。我通常通过保持一个表示我在xml层次结构中的位置的堆栈来完成此操作。
此外,单个characters
调用可能无法返回元素内的所有字符。允许XML解析器将元素的字符拆分为多个characters
事件。这意味着您需要使用startElement
和endElement
事件来创建/刷新使用characters
方法写入的缓冲区。
答案 1 :(得分:1)
重要提示:在覆盖startElement
之类的方法之前添加@Override。如果签名中有错误,编译器错误会说:不会覆盖任何方法。现在使用错误的参数类型,将调用DefaultHandler的startElement。
此外characters
可能不止一次被调用:
持有一个String变量
private StringBuilder elementValue;
在startElement中执行:
elementValue = new StringBuilder()
和字符,没有修剪:
elementValue.append(s);
并在endElement中保存它,现在是字符
peli.setName(elementValue.toString());
这适用于没有内部标记的叶元素。
答案 2 :(得分:1)
以下是正在发生的事情......对于元素的内容,方法characters
不一定只调用一次。字符数据可以由诸如注释,CDATA部分,处理指令等节点分解。即使不是这种情况,并且元素的内容是一个文本块,XML解析器可能决定以块的形式读取它,在换行符时将其分解,或者甚至在某些时候给你空字符串。
您需要做的是保留一个StringBuilder或类似的缓冲区,在调用characters
方法时附加指定的char [],并在调用方法endElement
后仅使用其完整值。之后,您可以清空构建器并再次开始使用它来构建下一个元素。
我还有一些额外的建议。无需使类Game
中的字段成为静态。对我来说,那些看起来应该是实例字段。我不知道这是一个学习如何编写SAX处理程序的任务或练习,但如果不是,这是一个更大的项目的一部分,我强烈建议你考虑使用JAXB,这是从XML到Java对象,反之亦然。