gpt4 book ai didi

java - xml:JAXB 中的基础

转载 作者:行者123 更新时间:2023-11-30 04:50:39 25 4
gpt4 key购买 nike

我有一些像这样的 XML:

<root xml:base="http://www.example.com/foo">
<childElement someAttribute="bar/blort.html"/>
<childElement someAttribute="bar/baz/foo.html"/>
</root>

我的 XML 架构将 someAttribute 定义为 xs:anyURI 类型

我想使用 JAXB 将 XML 解码到一个对象模型中,如下所示:

@XmlRootElement(name="root")
class Root {
@XmlElement(name="childElement")
private List<Child> _children;
}

class Child {
@XmlAttribute(name="someAttribute")
private URI _someAttribute;
}

我希望根据 XML 基础解析 someAttribute 的值,即当我解码上面给出的 XML 时,我希望将子属性解析为值为 http://www.example.com/foo/bar/blort.html 的 java.net.URI 实例。等等。

我希望自定义 XmlAdapter 能够让我获得正确的结果,但是 XmlAdapter 无法访问周围的上下文,特别是当时有效的 xml:base 的值(请注意,这并不像很简单,因为 xml:base 的最新封闭值可以出现在树中的任何位置,并且相对的 xml:base 必须根据其祖先进行解析。

如果重要的话,我正在使用 EclipseLink 的 MOXY JAXB 实现。

最佳答案

您可以利用 XMLStreamReaderXmlAdapter 来实现此用例:

UriAdapter

UriAdapter 既是一个用于处理 URI 属性的 XmlAdapter,也是我们将使用的 StreamFilter检测 xml:base 属性。

package forum9906642;

import java.net.URI;
import javax.xml.bind.annotation.adapters.*;
import javax.xml.stream.*;

public class UriAdapter extends XmlAdapter<String, URI> implements StreamFilter {

private String base = "";

public UriAdapter() {
}

public UriAdapter(String base) {
this.base = base;
}

public URI unmarshal(String string) throws Exception {
return new URI(base + '/' + string);
}

public String marshal(URI uri) throws Exception {
if("".equals(base)) {
return uri.toString();
} else {
URI baseURI = new URI(base);
return baseURI.relativize(uri).toString();
}
}

public boolean accept(XMLStreamReader reader) {
if(reader.isStartElement()) {
String newBase = reader.getAttributeValue("http://www.w3.org/XML/1998/namespace", "base");
if(null != newBase) {
base = newBase;
}
}
return true;
}

}

演示

下面的代码演示了如何一起使用所有部分:

package forum9906642;

import java.io.*;
import javax.xml.bind.*;
import javax.xml.stream.*;

public class Demo {

public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);

UriAdapter uriAdapter = new UriAdapter();

XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("src/forum9906642/input.xml"));
xsr = xif.createFilteredReader(xsr, uriAdapter);

Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setAdapter(uriAdapter);
Root root = (Root) unmarshaller.unmarshal(xsr);

for(Child child : root.getChildren()) {
System.out.println(child.getSomeAttribute().toString());
}

Marshaller marshaller = jc.createMarshaller();
marshaller.setAdapter(uriAdapter);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}

}

child

package forum9906642;

import java.net.URI;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;

@XmlAccessorType(XmlAccessType.FIELD)
class Child {

@XmlAttribute(name="someAttribute")
@XmlJavaTypeAdapter(UriAdapter.class)
private URI _someAttribute;

public URI getSomeAttribute() {
return _someAttribute;
}

public void setSomeAttribute(URI _someAttribute) {
this._someAttribute = _someAttribute;
}

}

输出

http://www.example.com/foo/bar/blort.html
http://www.example.com/foo/bar/baz/foo.html
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<childElement someAttribute="bar/blort.html"/>
<childElement someAttribute="bar/baz/foo.html"/>
</root>

关于java - xml:JAXB 中的基础,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9906642/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com