我正在尝试将设计不佳的XML解组为对象。 XML是使用通用type
元素构建的,该元素可以包含任意数量的items
和name
。根据下面type
中Something
的值,包含属性会有所不同。它基本上只是绕过了XSD的冲动(是的,它有一个XSD,但它完全没用)。
我得到的XML:
<Something type="actualType">
<Property name="prop1">value1</Property>
<Property name="prop2">value2</Property>
...
</Something>
应该是什么:
<actualType>
<prop1>Value1</prop1>
<prop2>Value2</prop1>
</actualType>
如何在Java中表示:
@XmlType(name="actualType")
public class ActualType
{
@XmlElement
public X prop1
@XmlElement
public Y prop2
}
实际问题:
在Jaxb中是否有类似这样的基本支持(没有外部依赖)?如果没有,我可以编写自定义注释,以便我可以使用此模式为其他服务重用相同的逻辑吗?
答案 0 :(得分:2)
您可以通过以下几种方式支持此用例:
选项#1 - 任何JAXB(JSR-222)实施
如果您只需要将XML读取到对象,那么您可以利用StreamReaderDelegate
并执行以下操作。基本上它会使坏的XML看起来好像是好的XML:
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.util.StreamReaderDelegate;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new StreamSource("src/forum16529016/input.xml"));
xsr = new StreamReaderDelegate(xsr) {
@Override
public String getLocalName() {
String localName = super.getLocalName();
if(!"Property".equals(localName) && super.getEventType() == XMLStreamReader.START_ELEMENT) {
return localName;
}
if(super.getEventType() == XMLStreamReader.START_ELEMENT) {
return super.getAttributeValue(null, "name");
}
return localName;
}
};
JAXBContext jc = JAXBContext.newInstance(ActualType.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
ActualType actualType = unmarshaller.unmarshal(xsr, ActualType.class).getValue();
System.out.println(actualType.prop1);
System.out.println(actualType.prop2);
}
}
选项#2 - EclipseLink JAXB(MOXy的)@XmlPath扩展
注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。
MOXy有@XmlPath
扩展名,可让您映射此用例。
import javax.xml.bind.annotation.XmlType;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlType(name="actualType")
public class ActualType
{
@XmlPath("Property[@name='prop1']/text())
public X prop1
@XmlPath("Property[@name='prop1']/text())
public Y prop2
}
了解更多信息
答案 1 :(得分:0)
这不是你问题的直接答案,但是你可以简单地读取坏对象,因为它们在对象Bad中,然后用构造函数Good(Bad bad)定义类Good。 Good类将属性定义为成员,其构造函数将从Bad对象中获取它们。
另一种方法是只有一个类,但保持“坏”成员私有,然后在解组之后调用一些方法来填充好成员(jaxb不受影响)。请参阅callback。