字符串变量在传递给另一个对象时会丢失它们的值

时间:2014-01-16 13:35:26

标签: java class variables

我正在尝试构建一个简单的程序来将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"到""如果我在调试中更进一步。

3 个答案:

答案 0 :(得分:1)

我对你的问题并不完全清楚,但我认为这就是问题所在:

解析器正在多次调用您的characters方法,其中一些方法只包含空格字符或没有字符。

致残:

<foo>
   <bar>The Text I Want</bar>
</foo>

在上面的XML中,解析器可以在characters</bar>之间自由调用</foo>,并且它将包含一些空格(如果格式化XML,则会显示标签和新行)。

在存储从characters检索到的信息之前,您应该验证您是否在正确的元素中。我通常通过保持一个表示我在xml层次结构中的位置的堆栈来完成此操作。

此外,单个characters调用可能无法返回元素内的所有字符。允许XML解析器将元素的字符拆分为多个characters事件。这意味着您需要使用startElementendElement事件来创建/刷新使用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对象,反之亦然。