- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我定义了以下 ObjectFactory
:
@XmlRegistry
public class ObjectFactory {
public Dogs createDogs() {
return new Dogs();
}
@XmlElementDecl(name = "dog")
public Dog createDog(DogType value) {
return new Dog(value);
}
@XmlElementDecl(name = "fido", substitutionHeadName = "dog", substitutionHeadNamespace = "")
public Dog createFido(DogType value) {
return new Dog("fido", value);
}
@XmlElementDecl(name = "barks", substitutionHeadName = "dog", substitutionHeadNamespace = "")
public Dog createBarks(DogType value) {
return new Dog("barks", value);
}
}
(Dogs
类很简单,Dog
和 DogType
见下文或 here。)
我正在解码以下 XML:
<listOfDogs>
<dogs>
<dog>
<name>henry</name>
<sound>bark</sound>
</dog>
<fido>
<sound>woof</sound>
</fido>
<barks>
<sound>miau</sound>
</barks>
</dogs>
</listOfDogs>
我真诚地期待 JAXB 会在解码期间调用我的 createFido(...)
和 createBarks(...)
方法。但这不会发生。 Dog
构造函数是通过反射直接调用的,不使用适当的 create...
方法。
我的问题是:
为什么在解码期间不调用 ObjectFactory
?
不应该吗?或者它只是一个用来保存 @XmlRegistry
/@XmlElementDecl
声明的虚拟对象?
我也查过这个问题:
What is the ObjectFactory role during JAXB-Unmarshalling?
解决方案是使用@XmlType.factoryClass
和factoryMethod
。这在这里不起作用,因为我不想将我的 DogType
静态链接到特定的实例化例程。我希望它在运行时根据元素名称来决定。我的目标是根据元素名称实例化相同但不同的类。
现在一些代码来完成它。
根元素类:
@XmlRootElement(name = "listOfDogs")
public class Dogs {
private List<JAXBElement<DogType>> dogs = new LinkedList<JAXBElement<DogType>>();
@XmlElementWrapper(name = "dogs")
@XmlElementRef(name = "dog")
public List<JAXBElement<DogType>> getDogs() {
return this.dogs;
}
@Override
public String toString() {
return "Dogs [dogs=" + dogs + "]";
}
}
Dog
,DogType
的包装元素类:
public class Dog extends JAXBElement<DogType> {
public static final QName NAME = new QName("dog");
private static final long serialVersionUID = 1L;
public Dog(DogType value) {
super(NAME, DogType.class, value);
}
public Dog(String dogName, DogType value) {
super(NAME, DogType.class, value);
}
@Override
public QName getName() {
final DogType value = getValue();
if (value != null && value.getName() != null) {
return new QName(value.getName());
} else {
return super.getName();
}
}
}
狗类型
:
public class DogType {
private String name;
private String sound;
public String getName() {
return name;
}
public void setName(String dogName) {
this.name = dogName;
}
public String getSound() {
return sound;
}
public void setSound(String sound) {
this.sound = sound;
}
}
测试:
public class DogTest {
@Test
public void unmarshallsDogs() throws JAXBException {
final JAXBContext context = JAXBContext
.newInstance(ObjectFactory.class);
final Dogs dogs = (Dogs) context.createUnmarshaller().unmarshal(
getClass().getResource("dogs.xml"));
Assert.assertEquals(3, dogs.getDogs().size());
// Does not work
// Assert.assertEquals("henry", dogs.getDogs().get(0).getValue()
// .getName());
Assert.assertEquals("bark", dogs.getDogs().get(0).getValue().getSound());
// Does not work
// Assert.assertEquals("fido", dogs.getDogs().get(1).getValue()
// .getName());
Assert.assertEquals("woof", dogs.getDogs().get(1).getValue().getSound());
// Does not work
// Assert.assertEquals("barks", dogs.getDogs().get(2).getValue()
// .getName());
Assert.assertEquals("miau", dogs.getDogs().get(2).getValue().getSound());
}
}
最佳答案
简短的回答是因为工厂方法没有生成到 @XmlType
注释中以告诉 JAXB 这样做:
@XmlRootElement(name = "listOfDogs")
@XmlType(factoryClass=ObjectFactory.class, factoryMethod="createDogs") // not generated
public class Dogs {
Shouldn't it be? Or is ist just a dummy to hold the @XmlRegistry/@XmlElementDecl declarations?
在我看来是的,它应该用于实例化类。
ObjectFactory
是对 JAXB 1.0 的倒退。在 JAXB 1.0 中,规范定义了生成的接口(interface)的外观,并且实现可以使用它们想要提供的任何 impl 来支持这些生成的接口(interface)。那时您需要使用 ObjectFactory
类以独立于供应商的方式创建您的模型。
JAXB 2.0 切换到 POJO 模型,您可以在其中自由使用默认构造函数。如果 JAXB 1.0 从未存在过,是否会有 ObjectFactory
类,这很难说。由于 ObjectFactory
类以前存在,因此保留了几个原因:
@XmlElementDecl
为一个类指定多个根元素。 @XmlRegistry
注释实际上只是一个标记注释,用于指示包含 @XmlElementDecl
注释的类,而不将其限制为名为 ObjectFactory
的类.您的用例可以通过 XmlAdapter
实现,尽管我不清楚您在 ObjectFactory
中尝试拥有什么逻辑。
XmlAdapter (DogAdapter)
您的自定义逻辑在 XmlAdapter
上进行。
import javax.xml.bind.*;
import javax.xml.bind.annotation.adapters.*;
public class DogAdapter extends XmlAdapter<JAXBElement<DogType>, JAXBElement<DogType>> {
@Override
public JAXBElement<DogType> unmarshal(JAXBElement<DogType> v) throws Exception {
return new Dog(v.getName().getLocalPart(), v.getValue());
}
@Override
public JAXBElement<DogType> marshal(JAXBElement<DogType> v) throws Exception {
return v;
}
}
狗
XmlAdapter
是从 @XmlJavaTypeAdapter
注释中引用的。
import java.util.*;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "listOfDogs")
public class Dogs {
private List<JAXBElement<DogType>> dogs = new LinkedList<JAXBElement<DogType>>();
@XmlElementWrapper(name = "dogs")
@XmlElementRef(name = "dog")
@XmlJavaTypeAdapter(DogAdapter.class)
public List<JAXBElement<DogType>> getDogs() {
return this.dogs;
}
@Override
public String toString() {
return "Dogs [dogs=" + dogs + "]";
}
}
对象工厂
ObjectFactory
现在是一个仅包含 @XmlElementDecl
注释的哑类:
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
public Dogs createDogs() {
return new Dogs();
}
@XmlElementDecl(name = "dog")
public JAXBElement<DogType> createDog(DogType value) {
return new Dog(value);
}
@XmlElementDecl(name = "fido", substitutionHeadName = "dog", substitutionHeadNamespace = "")
public JAXBElement<DogType> createFido(DogType value) {
return new JAXBElement<DogType>(new QName("fido"), DogType.class, value);
}
@XmlElementDecl(name = "barks", substitutionHeadName = "dog", substitutionHeadNamespace = "")
public JAXBElement<DogType> createBarks(DogType value) {
return new JAXBElement<DogType>(new QName("barks"), DogType.class, value);
}
}
My question, however is more about the specification. According to the spec, should the create* methods from the ObjectFactory be executed or not?
在 JAXB 2 中,从头开始创建的模型与从 XML 模式生成的模型没有区别。因此,您需要查看规范中关于类的内容。根据下面的引用,它归结为无参数构造函数或指定的工厂方法。
来自 JAXB 2.2 (JSR-222) 的 8.7.1.2 映射 部分规范:
a class must have a public or protected no-arg constructor or a factory method identified by {factoryClass(), factoryMethod()} unless it is adapted using @XmlJavaTypeAdapter.
关于java - 为什么在解码期间不使用 ObjectFactory?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26439184/
我需要从 java 客户端将数据协定传递到我的 wcf web 服务。数据契约(Contract)有 2 个归档,都是字符串。创建代理后,我正在尝试的代码如下 FileTransfer fs = ne
尝试实例化 ObjectFactory 时,我在 Eclipse 中收到以下编译错误: cannot instantiate the type objectfactory 此编译错误在以下行抛出: o
我正在尝试在来自第 3 方的 WSDL 中执行 wsimport(通过 netbeans 6.9.1),但它一直在 JAXB 中生成此错误: Two declarations cause a coll
我定义了以下 ObjectFactory: @XmlRegistry public class ObjectFactory { public Dogs createDogs() {
我有一个使用默认值的 WSDL 文件,我想生成 ObjectFactory 类,这些类使用 CXF 创建具有这些默认值的方法。例如,我有一个这样定义的对象
我正在使用 docx4j 创建一个 Word 文档,并且需要设置“标题”的样式,但是,我找不到执行此操作的正确函数。 private static P createIt() { org.doc
我尝试在结构图中注册命名实例。但是我的试验没有成功。 正确的做法是什么? 目前我是这样做的: IService bus = CreateInstanceOfServiceBus(); ObjectFa
使用 AngularFire,我正在扩展对象工厂,以便封装数据并允许特定功能,如 official tutorial 中所述。 .我有一个如下的数据结构: { 'articles': {
我正在创建一个 JAXBElement具有 ObjectFactory 的元素. 该对象是使用 null 创建的值,因为该字段的架构表明它有一个 nillable属性。 在编码到 xml 期间,输出文
我有两个 xsd 导入到主 xsd 中。两者具有相同的元素,但命名空间不同。因此,我为第二个 xsd(B.xsd) 创建了自定义绑定(bind)。我仍然收到“两个声明导致 ObjectFactory
我正在使用 JAXB 为导入其他模式的模式生成类。我正在使用 maven 并将 maven-jaxb2 插件配置为使用依赖项作为情节,跳过为导入的模式生成类。 然而,JAXB 不断为导入的模式生成 O
我使用 StructureMap 实现了接口(interface)注入(inject),如下所述。 ObjectFactory.Initialize(x => { x.For().Use(); });
要在 GlassFish Server 开源版 3.1.1(内部版本 12)中部署: Caused by: java.security.PrivilegedActionException: com.s
我有一个大型应用程序,它使用使用 ObjectFactory.GetInstance() 获取实例的旧方法。 现在我想将应用程序转移到使用构造函数注入(inject)注入(inject)依赖项的更正确
这是重现问题的简单测试,这是整个项目中的单个类,没有其他引用: [TestFixture] public class ObjectFactoryTests { [Test] publi
在使用最新的 StructureMap 版本 (3.1.6.191) 升级我们的解决方案后,我收到了很多过时的警告。这些警告来自 StructureMap,其中 ObjectFactory 类将在未来
我正在尝试制作网络服务,但我遇到了两种情况。 xsd 文件有两种类型,第一种是:
我正在开发一个工厂,它可以使用 Class 参数实例化 Skill 类型的对象。该工厂的代码是: public static final class AbilityFactory { priv
我有一个 XSD 选择,它们都是 javax.xml.datatype.XMLGregorianCalendar 类型。按照建议,我使用了 ObjectFactory 和 JAXBElement 来区
我们已经在我们的系统中使用 JAXB 2.1 很长时间了。我们有一个使用 Ant 构建的平台,并生成一堆部署在 OSGi 运行时中的包。我们使用 Java SE 6。 我们在构建过程中使用 JAXB
我是一名优秀的程序员,十分优秀!