Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java中的自定义对象实现将XML解析为DOM树_Java_Xml_Parsing_Dom - Fatal编程技术网

使用Java中的自定义对象实现将XML解析为DOM树

使用Java中的自定义对象实现将XML解析为DOM树,java,xml,parsing,dom,Java,Xml,Parsing,Dom,我想将XML文档解析为Java中的DOM树,这样树中的某些对象(例如org.w3c.DOM.Node或org.w3c.DOM.Element)可以向下转换为我创建的类的实例,同时最小化我需要(重新)实现的XML相关代码的数量。作为一个(非常简单)的示例,如果我有一个XML元素,如: <Vector size="5"> 1.0 -1.0 3.0 -2.73e2 </Vector> 这样我就可以将解析器创建的Vector的实例传递给对象的方法,例如javax.xml.x

我想将XML文档解析为Java中的DOM树,这样树中的某些对象(例如
org.w3c.DOM.Node
org.w3c.DOM.Element
)可以向下转换为我创建的类的实例,同时最小化我需要(重新)实现的XML相关代码的数量。作为一个(非常简单)的示例,如果我有一个XML元素,如:

<Vector size="5">
  1.0 -1.0 3.0 -2.73e2
</Vector>

这样我就可以将解析器创建的
Vector
的实例传递给对象的方法,例如
javax.xml.xpath
对象的方法,并使它们正常工作。实现这一目标的最快方法是什么?单独使用Java SE是否可能,或者是否需要第三方库(例如Xerces)?

我不确定您的需求是什么,但假设您可以控制XML的外观,我会使用它。它将允许您完全跳过所有DOM操作


从现在开始,它可能看起来不像是为这个用例而构建的,但实际上是。首先创建java类,确保它们按照您希望的方式生成XML,然后使用它将已经存在的XML作为XStream对象读回程序中。这是一个很好用的图书馆

注意:我是专家组的负责人和成员

JAXB中的
Binder
机制可能就是您想要的。它不允许将DOM节点强制转换为域对象,但它确实维护域对象与其对应的DOM节点之间的链接

注意:以下代码在使用MOXy作为JAXB提供程序时运行正常,但在使用我正在运行的JDK版本中包含的JAXB impl时引发了异常

JAVA模型

我将在这个示例中使用以下域模型

客户

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Customer {

    private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

    @XmlElementWrapper
    @XmlElement(name="phoneNumber")
    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

}
import javax.xml.bind.annotation.*;

public class PhoneNumber {

    private String type;
    private String number;

    @XmlAttribute
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @XmlValue
    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

}
jaxb.properties

要将MOXy指定为您的JAXB提供程序,您需要在与域模型相同的包中包含一个名为
JAXB.properties
的文件,其中包含以下条目(请参阅:)

XML(input.XML)

输出

555-2OBJ
555-2DOM

在过去的10年中,我一直在做这件事,为化学、图形、数学等构建XML DOM。我自己的解决方案是使用DOM,在DOM中可以对元素进行子类化(我使用xom.nu,但还有其他一些)。W3CDOM不允许子类化(IIRC),因此您必须构建一个委托模型。(我在很多年前尝试过这个方法,但拒绝了它,但软件工具和库使这一切变得更容易(例如IDE将生成delegat方法)

如果您做了很多工作,尤其是创建了很多自定义方法,那么我建议您使用自己的系统。工作将在您的方法(dotProduct)中进行,而不是在XML中

例如,在这里

(它扩展了基类cmlement,它扩展了nu.xom.Element

元素的创建是一个工厂。下面是我的SVGDOM的一块:

public static SVGElement readAndCreateSVG(Element element) {
    SVGElement newElement = null;
    String tag = element.getLocalName();
    if (tag == null || tag.equals(S_EMPTY)) {
        throw new RuntimeException("no tag");
    } else if (tag.equals(SVGCircle.TAG)) {
        newElement = new SVGCircle();
    } else if (tag.equals(SVGClipPath.TAG)) {
        newElement = new SVGClipPath();
    } else if (tag.equals(SVGDefs.TAG)) {
        newElement = new SVGDefs();
    } else if (tag.equals(SVGDesc.TAG)) {
        newElement = new SVGDesc();
    } else if (tag.equals(SVGEllipse.TAG)) {
        newElement = new SVGEllipse();
    } else if (tag.equals(SVGG.TAG)) {

...
    } else {
            newElement = new SVGG();
            newElement.setClassName(tag);
            System.err.println("unsupported svg element: "+tag);
        }
        if (newElement != null) {
            newElement.copyAttributesFrom(element);
            createSubclassedChildren(element, newElement);
        }
        return newElement;
您可以看到用于复制和递归的工具

你需要考虑的问题是:

  • 这与XSD的绑定有多紧密
  • 我是否使用XSD数据类型
  • 我是否验证输入
  • 我是否使用DOM作为主要数据结构(我使用)
  • 事情会多久改变一次

FWIW我已经经历了6次修订,正在考虑另一次修订(使用Scala作为主引擎)。

您是否控制XML的外观?是的,我完全控制XML及其模式。我需要对我的对象(即其成员)进行更改立即反映在DOM中。XStream似乎实例化了一组独立于DOM的对象。为什么需要DOM?主要是使用XPath来导航XML层次结构。@TechnocratiK但您可以将整个文件读入对象树并遍历对象中的数据,避免使用XPath。如果您喜欢使用XPath,那么XStream不适合你。但是如果你想将XML提取到对象,XStream是最好的工具。我不知道有什么东西能做到一半。
<?xml version="1.0" encoding="UTF-8"?>
<customer>
    <phoneNumbers>
        <phoneNumber type="work">555-1111</phoneNumber>
        <phoneNumber type="home">555-2222</phoneNumber>
    </phoneNumbers>
</customer>
import javax.xml.bind.Binder;
import javax.xml.bind.JAXBContext;
import javax.xml.parsers.*;
import javax.xml.xpath.*;

import org.w3c.dom.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse("src/forum16599580/input.xml");

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();

        JAXBContext jc = JAXBContext.newInstance(Customer.class);
        Binder<Node> binder = jc.createBinder();
        binder.unmarshal(document);

        // Use Node to Get Object
        Node phoneNumberElement = (Node) xpath.evaluate("/customer/phoneNumbers/phoneNumber[2]", document, XPathConstants.NODE);
        PhoneNumber phoneNumber = (PhoneNumber) binder.getJAXBNode(phoneNumberElement);

        // Modify Object to Update DOM
        phoneNumber.setNumber("555-2OBJ");
        binder.updateXML(phoneNumber);
        System.out.println(xpath.evaluate("/customer/phoneNumbers/phoneNumber[2]", document, XPathConstants.STRING));

        // Modify DOM to Update Object
        phoneNumberElement.setTextContent("555-2DOM");
        binder.updateJAXB(phoneNumberElement);
        System.out.println(phoneNumber.getNumber());
    }

}
555-2OBJ
555-2DOM
public class CMLPoint3 extends AbstractPoint3 
public static SVGElement readAndCreateSVG(Element element) {
    SVGElement newElement = null;
    String tag = element.getLocalName();
    if (tag == null || tag.equals(S_EMPTY)) {
        throw new RuntimeException("no tag");
    } else if (tag.equals(SVGCircle.TAG)) {
        newElement = new SVGCircle();
    } else if (tag.equals(SVGClipPath.TAG)) {
        newElement = new SVGClipPath();
    } else if (tag.equals(SVGDefs.TAG)) {
        newElement = new SVGDefs();
    } else if (tag.equals(SVGDesc.TAG)) {
        newElement = new SVGDesc();
    } else if (tag.equals(SVGEllipse.TAG)) {
        newElement = new SVGEllipse();
    } else if (tag.equals(SVGG.TAG)) {

...
    } else {
            newElement = new SVGG();
            newElement.setClassName(tag);
            System.err.println("unsupported svg element: "+tag);
        }
        if (newElement != null) {
            newElement.copyAttributesFrom(element);
            createSubclassedChildren(element, newElement);
        }
        return newElement;