我的模型元素可能包含几个不同类型的子元素。对于每种类型,可能只存在0或1个子元素。定义了这些元素的顺序,即类型A的所有元素都在B之前。我的模型类由JAXB生成,因此应该为每种类型的子元素都有一个单独的getter / setter属性。
使事情变得复杂的是上述规则的一个例外:在子元素列表的开头和结尾处,每个元素可能出现0或1个X元素,并且这些元素都具有相同的名称。 / p>
这是我当前现实生活XSD类型的略微简化版本:
<xs:complexType name="Activity">
<xs:sequence>
<xs:element name="log" type="DiagnosticLogMessage" minOccurs="0" maxOccurs="1" />
<xs:element name="inputs" type="Mappings" minOccurs="0" maxOccurs="1" />
<xs:element name="outputs" type="Mappings" minOccurs="0" maxOccurs="1" />
<xs:element name="log" type="DiagnosticLogMessage" minOccurs="0" maxOccurs="1" />
<xs:element name="to" type="DirectConnection" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
“log”是有问题的元素。使用上面的类型定义,“to”正确获取其自己的属性,但其余元素将进入名为“logsAndInputsAndOutputs”的列表中。如果我将两个“log”元素重命名为“logBefore”和“logAfter”,则每个元素都有自己的属性,所以很明显问题是JAXB无法区分这两个“日志”。
我理解XSD本身并不是非常精确:它允许单个“log”类型的子元素,在这种情况下,如果将其视为“before”或“after”元素,则它是未定义的。在我当前(手动编写的)读者类中,我有明确的代码来检测这种情况并将单个“log”元素解释为“before”元素。
我正在寻找一种方法来告诉JAXB以不同方式处理这两个“log”元素,或者通过xjb映射,或者可能使用更具体的XSD。
答案 0 :(得分:1)
注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。
以下是利用MOXy @XmlPath
扩展程序处理此用例的方法。
XML架构(schema.xsd)
以下是基于您在问题中提供的片段的XML架构。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:forum17408865" xmlns="urn:forum17408865"
elementFormDefault="qualified">
<xs:element name="foo">
<xs:complexType>
<xs:sequence>
<xs:element name="bar" type="Activity"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Activity">
<xs:sequence>
<xs:element name="log" type="DiagnosticLogMessage"
minOccurs="0" maxOccurs="1" />
<xs:element name="inputs" type="Mappings" minOccurs="0"
maxOccurs="1" />
<xs:element name="outputs" type="Mappings" minOccurs="0"
maxOccurs="1" />
<xs:element name="log" type="DiagnosticLogMessage"
minOccurs="0" maxOccurs="1" />
<xs:element name="to" type="DirectConnection" minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="DiagnosticLogMessage" />
<xs:complexType name="Mappings" />
<xs:complexType name="DirectConnection" />
</xs:schema>
<强>活动强>
MOXy具有@XmlPath
扩展名,允许您根据其位置映射到XML元素。无法从XML模式生成此类,因此我们将自己创建它。
package forum17408865;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder={"log1", "inputs", "outputs", "log2", "to"})
public class Activity {
@XmlPath("log[1]")
private DiagnosticLogMessage log1;
private Mappings inputs;
private Mappings outputs;
@XmlPath("log[2]")
private DiagnosticLogMessage log2;
private DirectConnection to;
}
<强> binding.xml 强>
要让JAXB使用我们手动创建的类,我们将利用JAXB绑定文件。
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings schemaLocation="schema.xsd">
<jxb:bindings node="//xs:complexType[@name='Activity']">
<jxb:class ref="forum17408865.Activity" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
XJC致电
以下是利用绑定文件的XJC调用。请注意我们还需要使用-nv
标志来禁用模式验证。
xjc -nv -b binding.xml schema.xs
了解更多信息