3

我正在尝试将设计不佳的 XML 解组到一个对象中。XML 是使用通用type元素构建的,该元素可以具有任意数量的items任意name. 根据以下typein的值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(没有外部依赖项)中是否对类似的东西有任何基本支持?如果没有,我是否可以编写自定义注释,以便我能够为使用此模式的其他服务重用相同的逻辑?

4

2 回答 2

2

有几种方法可以支持这个用例:

选项 #1 - 任何 JAXB (JSR-222) 实现

如果您只需要读取 XML 到对象,那么您可以利用 aStreamReaderDelegate并执行以下操作。基本上它使坏的 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

}

了解更多信息

于 2013-05-13T19:04:37.737 回答
0

这不是您问题的直接答案,但您可以简单地读取坏 xml,因为它们在对象 Bad 中,然后使用构造函数 Good(Bad bad)定义类 Good。Good 类将属性定义为成员,其构造函数将从 Bad 对象中获取它们。

另一种方法是只有一个类,但将“坏”成员保持私有,然后在解组后调用一些方法来填充好成员(jaxb 未触及这些成员)。见回调

于 2013-05-14T21:00:09.327 回答