【问题标题】:Extend a JDOM Document扩展 JDOM 文档
【发布时间】:2016-01-21 09:10:33
【问题描述】:

对于大学的一个项目,我需要解析一个 GML 文件。 GML 文件是基于 XML 的,所以我使用 JDOM2 来解析它。为了符合我的目的,我像这样扩展了 org.jdom2.Document:

package datenbank;

import java.io.File;
// some more imports

public class GMLDatei extends org.jdom2.Document {

    public void saveAsFile() {
        // ...
    }

    public GMLKnoten getRootElement(){
        return (GMLKnoten) this.getDocument().getRootElement();
    }

    public void setRootElement(GMLKnoten root){
        this.getDocument().setRootElement(root);
    }
}

我还扩展了 org.jdom2.Element 并将子类命名为 GMLKnoten,但这对我的问题来说并不重要。

测试时,我尝试加载 GML 文件。使用本机文档和元素类​​时,它可以正常加载,但是在使用我的子类时,我会遇到以下情况:

我使用以下方式加载文件:

SAXBuilder saxBuilder = new SAXBuilder();
File inputFile = new File("gml/Roads_Munich_Route_Lines.gml");
GMLDatei document = null;

ArrayList<String> types = new ArrayList<String>();

try {
    document = (GMLDatei) saxBuilder.build(inputFile);
} catch (JDOMException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

排队

document = (GMLDatei) saxBuilder.build(inputFile);

我得到一个 Cast-Exception:

Exception in thread "main" java.lang.ClassCastException: org.jdom2.Document cannot be cast to datenbank.GMLDatei
at datenbank.GMLTest.main(GMLTest.java:27)

我认为转换应该没有问题,因为我是 org.jdom2.document 的子类。我错过了什么?

大桶

【问题讨论】:

  • 这很容易。 SAXBuilder 返回 org.jdom2.Document 而不是 GMLDatei。如果您真的想实现这一点,则必须重新实现/扩展 SAXBuilder 以创建 GMLDatei 而不是基本的 Document
  • @ParkerHalo 是的,我知道,但我记得使用这种方法已经很久了,例如扩展一个 JTable 并且它起作用了。
  • hm...也许您当时自己创建了对象(带有关键字 new 的新实例)但是这里的问题是 SAXParser 创建了您的文档实例!
  • 在调用 SAXBuilder 之前,我将它实例化为 null 一些行
  • 好吧,我看到您在这里缺少一些基本知识(无意冒犯)。方法saxBuilder.build(inputFile) 创建了一个org.jdom2.Document 的新实例(对象),它不是GMLDatei 类型。在您的行中,您尝试将 Document 类型的对象解析为 GMLDatei 这是不可能的

标签: java jdom-2


【解决方案1】:

一般来说,我想“挑战”您扩展 Document 的要求 - 您从尚未成为本机实现一部分的自定义类中获得什么价值?我问这个有两个原因:

  • 作为 JDOM 的维护者,我是否应该添加一些新功能?
  • 我只是好奇.....

JDOM 有一个系统允许您扩展它的核心类并在解析文档时对它们进行不同的实现。它是通过扩展JDOMFactory 来完成的。

在此处考虑此代码:JDOMFactory interface。当SAXParser 解析文档时,它会使用这些方法来构建文档。

DefaultJDOMFactory 中有一个默认的、可覆盖的实现,您可以扩展它,例如,在您的实现中,您必须覆盖非最终的“元素”方法,例如:

@Override
public Element element(final int line, final int col, final String name,
      String prefix, String uri) {
  return new Element(name, prefix, uri);
}

而是有:

@Override
public Element element(final int line, final int col, final String name,
        String prefix, String uri) {
    return new GMLKnoten (name, prefix, uri);
}

请注意,您必须覆盖所有非最终方法并返回要自定义的内容(例如,您必须根据我的计数覆盖 4 个 Element 方法。

使用您自己的GMLJDOMFactory,您可以通过使用full constructor new SAXBuilder(null, null, new GMPJDOMFactory()) 或设置JDOMFactory after you have constructred it with setJDOMFactory(...) 来使用SAXBuilder

【讨论】:

  • 我们对 JDOM 类进行子类化有两个不同的原因。 GMLDatei(子类文档):我们在设计类图时不知道 XMLOutputter,现在改变一切为时已晚
  • GMLKnoten(子类元素):当使用 JDOM 的 getChild- 和 getChildren-Methods 时,尽管我们想要获取的孩子存在,但我们总是返回 null。
  • @vatbub - 没有得到您期望的孩子的最常见原因是因为他们不在您查询的命名空间中。在查询命名空间中的子元素时,您将始终需要使用命名空间参数。
猜你喜欢
  • 1970-01-01
  • 2019-09-15
  • 2015-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
相关资源
最近更新 更多