JAXB-обработка XML-последовательностей - PullRequest
13 голосов
/ 30 ноября 2011

Я пытаюсь обработать некоторые XML-файлы, используя реализацию JAXB, поставляемую в Java 7. Я использую следующие версии:

501 ~ % xjc -version
xjc 2.2.4
502 ~ %java -version        
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) Server VM (build 21.1-b02, mixed mode)

Проблематичным удалением в XML-схеме является следующее:

<xsd:complexType name="CategorizeType">
    <xsd:complexContent>
        <xsd:extension base="se:FunctionType">
            <xsd:sequence>
                <xsd:element ref="se:LookupValue"/>
                <xsd:element ref="se:Value"/>
                <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                    <xsd:element ref="se:Threshold"/>
                    <xsd:element ref="se:Value"/>
                </xsd:sequence>
                <xsd:element ref="se:Extension" minOccurs="0" />
            </xsd:sequence>
            <xsd:attribute name="thresholdBelongsTo"
                  type="se:ThresholdBelongsToType" use="optional"/>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

Как видите, есть два явных события se: значение в типе. Тем не менее, это не останавливает компиляцию с использованием xjc. И если я загляну в класс Java, сгенерированный для этого типа, я вижу, что теоретически возможно получить элементы

 <xsd:sequence minOccurs="0" maxOccurs="unbounded">
     <xsd:element ref="se:Threshold"/>
     <xsd:element ref="se:Value"/>
 </xsd:sequence>

используя следующий метод:

public List<Object> getThresholdAndValue() {
    if (thresholdAndValue == null) {
        thresholdAndValue = new ArrayList<Object>();
    }
    return this.thresholdAndValue;
}

К сожалению, если я попытаюсь получить элементы списка, я смогу получить только те элементы, которые зарегистрированы как пороговые значения в моем xml-файле, где экземпляр CategoryorizeType определен следующим образом:

 <Categorize thresholdsBelongTo="succeeding" fallbackValue="0">
     <LookupValue>
         <ns3:ValueReference>OUI_EEE92</ns3:ValueReference>
     </LookupValue>
     <Value>0.3</Value>
     <Threshold>30.0</Threshold>
     <Value>0.4</Value>
     <Threshold>40.0</Threshold>
     <Value>0.45</Value>
     <Threshold>45.0</Threshold>
     <Value>0.5</Value>
     <Threshold>50.0</Threshold>
     <Value>0.55</Value>
     <Threshold>55.0</Threshold>
     <Value>0.6</Value>
     <Threshold>60.0</Threshold>
     <Value>0.7</Value>
     <Threshold>70.0</Threshold>
     <Value>0.8</Value>
     <Extension>
         <ExtensionParameter name="method">MANUAL</ExtensionParameter>
     </Extension>
 </Categorize>

При получении списка я вижу только значения Threshold.

Я что-то не так делаю? Это внутреннее ограничение Jaxb?

Обратите внимание, что я не могу изменить схему XML ...

РЕДАКТИРОВАТЬ:

Я только что запустил xjc с опцией -v, и я получил глобально такой же вывод С многословием:

xjc -verbose se/2.0/All.xsd
parsing a schema...
[WARNING] java.net.SocketException: Unexpected end of file from server
  line 23 of file:/home/alexis/crap/SE-Schema-2.0/ows/2.0/ows19115subset.xsd

[WARNING] java.net.SocketException: Unexpected end of file from server
  line 22 of file:/home/alexis/crap/SE-Schema-2.0/filter/2.0/filterCapabilities.xsd

compiling a schema...
[INFO] generating codee
unknown location

без него:

xjc se/2.0/All.xsd 
parsing a schema...
[WARNING] java.net.SocketException: Unexpected end of file from server
  line 23 of file:/home/alexis/crap/SE-Schema-2.0/ows/2.0/ows19115subset.xsd

[WARNING] java.net.SocketException: Unexpected end of file from server
  line 22 of file:/home/alexis/crap/SE-Schema-2.0/ows/2.0/owsExceptionReport.xsd

compiling a schema...

Следующий вывод содержит только имя и расположение сгенерированных файлов.

Я забыл сказать, что этот xsd не может быть скомпилирован с xjc, поставляемым с Java 6. Последняя попытка была сделана с JAXB 2.1.10. Я не могу воспроизвести это поведение сейчас, так как я сейчас работаю с Java 7.

РЕДАКТИРОВАТЬ2:

Я только что попытался настроить binginds, как предложено в комментариях. Мой файл привязки следующий:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jxb:bindings jxb:version="1.0"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"    >
    <jxb:bindings schemaLocation="schema.xsd" 
                   node="//xsd:complexType[@name='CategorizeType']">
        <jxb:bindings 
                  node="xsd:complexContent/xsd:extension/xsd:sequence/xsd:element[@ref='se:Value'][position()=1]">
            <jxb:property name="FirstValue"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

Первый экземпляр значения действительно заменяется атрибутом firstValue в коде Java

@XmlElement(name = "Value", required = true)
protected ParameterValueType firstValue;
@XmlElements({
    @XmlElement(name = "Threshold", type = LiteralType.class),
    @XmlElement(name = "Value", type = ParameterValueType.class)
})
protected List<Object> thresholdAndValue;

public ParameterValueType getFirstValue() {
    return firstValue;
}
public void setFirstValue(ParameterValueType value) {
    this.firstValue = value;
}
public List<Object> getThresholdAndValue() {
    if (thresholdAndValue == null) {
        thresholdAndValue = new ArrayList<Object>();
    }
    return this.thresholdAndValue;
}

К сожалению, я все еще получаю тот же результат - я все еще не вижу свои значения в списке, возвращаемом getThresholdAndValues ​​(). Я все еще изучаю способ настройки ...

Ответы [ 2 ]

4 голосов
/ 06 декабря 2011

Обновление: Извините, что пришлось отказаться от этого, я просто не мог заставить его работать (было бы намного проще, если бы вы могли изменить свою схему!). Я использовал Codehaus JAXB maven плагин . Я почти уверен, что это конфликт, вызванный двумя элементами Value , которые я попытался исправить с помощью настройки xjb:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jxb:bindings jxb:version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings schemaLocation="../xsd/example.xsd" node="/xsd:schema">
        <jxb:schemaBindings>
            <jxb:package name="com.example" />
            <jxb:nameXmlTransform>
                <jxb:elementName suffix="Element"/>
            </jxb:nameXmlTransform>
        </jxb:schemaBindings>
    </jxb:bindings>
</jxb:bindings>

Это не имело абсолютно никакого эффекта. Я попытался <jxb:typeName suffix="Element"/>, и он переименовал все классы JAXB, поэтому я предполагаю, что есть ошибка с функцией jxb:elementName.

Исходное сообщение:

Я смотрю на это и могу воспроизвести вашу проблему.

Я воспользовался вашей схемой, чтобы упростить вещи, но она все еще содержит необходимые элементы. Вот что я использовал:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:se="http://com.example/example" 
        targetNamespace="http://com.example/example"
    elementFormDefault="qualified">

    <xsd:element name="Categorize" type="se:CategorizeType" />

    <xsd:complexType name="FunctionType">
    </xsd:complexType>

    <xsd:simpleType name="Value">
        <xsd:restriction base="xsd:string"/>
    </xsd:simpleType>

    <xsd:simpleType name="Threshold">
        <xsd:restriction base="xsd:string"/>
    </xsd:simpleType>

    <xsd:complexType name="CategorizeType">
        <xsd:complexContent>
            <xsd:extension base="se:FunctionType">
                <xsd:sequence>
                    <xsd:element name="Value" type="se:Value" />
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="Threshold" type="se:Threshold" />
                        <xsd:element name="Value" type="se:Value" />
                    </xsd:sequence>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>

Я удалил все элементы / атрибуты, не относящиеся к проблеме, использовал name/type вместо ref и определил типы, отсутствующие в предоставленной вами схеме.

Мой сгенерированный класс JAXB Category_Type выглядит так:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CategorizeType", propOrder = {
    "value",
    "thresholdAndValue"
})
public class CategorizeType
    extends FunctionType
{

    @XmlElement(name = "Value", required = true)
    protected String value;
    @XmlElementRefs({
        @XmlElementRef(name = "Value", 
            namespace = "http://com.example/example", type = JAXBElement.class),
        @XmlElementRef(name = "Threshold", 
            namespace = "http://com.example/example", type = JAXBElement.class)
    })
    protected List<JAXBElement<String>> thresholdAndValue;

    ...
}

Когда я отменяю ваш XML, мое Категоризация.Значение равно 0.8 (вместо ожидаемого 0.3), а значения каждого ThresholdAndValue (все Strings в моем случае) равны 30.0, 40.0, 45.0 и т. Д. 0.4, 0.45 и т. Д. Отсутствуют.

Когда я удаляю первый элемент Value из схемы и затем отменяю, я получаю все ожидаемые значения, так что, безусловно, существует конфликт!

Однако, когда я использую следующую настройку JAXB:

ObjectFactory factory = new ObjectFactory();
CategorizeType catType = factory.createCategorizeType();
catType.setValue("0.3");
JAXBElement<String> thresh = factory.createCategorizeTypeThreshold("30.0");
JAXBElement<String> threshVal = factory.createCategorizeTypeValue("0.4");
JAXBElement<String> thresh2 = factory.createCategorizeTypeThreshold("40.0");
JAXBElement<String> threshVal2 = factory.createCategorizeTypeValue("0.45");
catType.getThresholdAndValue().add(thresh);
catType.getThresholdAndValue().add(threshVal);
catType.getThresholdAndValue().add(thresh2);
catType.getThresholdAndValue().add(threshVal2);
JAXBElement<CategorizeType> element = factory.createCategorize(catType);
// marshall to XML here!

Я получаю ожидаемый результат:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Categorize xmlns="http://com.example/example">
    <Value>0.3</Value>
    <Threshold>30.0</Threshold>
    <Value>0.4</Value>
    <Threshold>40.0</Threshold>
    <Value>0.45</Value>
</Categorize>

Я буду продолжать изучать это!

1 голос
/ 06 декабря 2011

я думаю, что вам нужен элемент complexType около

            <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                <xsd:element ref="se:Threshold"/>
                <xsd:element ref="se:Value"/>
            </xsd:sequence>

Можно ли вставить XSLT-преобразование, чтобы добавить ComplexType в определение схемы перед запуском xjc?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...