Сохранение нескольких xsd: any с JAXB с использованием @XmlAnyElement - PullRequest
1 голос
/ 24 ноября 2010

Как я могу поддерживать с чередованием неизвестно XML с использованием JAXB?Использование @ XmlAnyElement не похоже на работу ..

Я пытаюсь написать схему XML, чтобы разрешить чередующиеся элементы из других пространств имен, и использовать это со встроеннымJAXB в Java 6. (Я не пробовал это полностью с JAXB 2.2.1, так как у меня нет роскоши требовать от моих пользователей API делать магию с поддержкой библиотек JAXB, но я верю в этотоже не работает с 2.2.1)

Так, например, учитывая схему everything.xsd , этот example.xml должен быть действительным:

<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://example.com/schema"
    xmlns:other="http://example.com/other">
    <rootFiles>
        <other:before>before rootFile</other:before>
        <rootFile path="test" />
        <other:after>after rootFile</other:after>
    </rootFiles>
</container>

Любой XML из других пространств имен должен быть разрешен как до, так и после <rootFile>.


Схематически это довольно просто, используя элементы <xsd:any> до и после <xsd:element> за <rootFile>. Чередование вокруг необязательных элементов сложнее, но это отдельный пост.Уловка заключается в том, чтобы вместо этого сделать необязательной группу оберток: <xsd:sequence minOccurs="0"><xsd:element minOccurs="1" .. /><xsd:any /></xsd:sequence>

Я добавил jaxb: свойство , чтобы указать различные имена свойств для свойств any до / после.Я должен был сделать это, чтобы XJC не жаловался на Свойство «Any» уже определено .

Проблема в том, что JAXB, кажется, забрасывает все неизвестные элементы в anyBefore свойство, как видно при повторной сортировке неупорядоченного элемента (см. полный пример Maven Project ):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container xmlns="http://example.com/schema">
    <rootFiles>
        <other:before xmlns:other="http://example.com/other">before rootFile</other:before>
        <other:after xmlns:other="http://example.com/other">after rootFile</other:after>
        <rootFile path="test"/>
    </rootFiles>
</container>

Это делает невозможным проверку rootFiles.getAnyAfter(), чтобы увидеть, какие неизвестные пришлигде, но более серьезно для меня, невозможно снова сериализовать XML без возражений по поводу чередующегося XML.

XJC правильно создает два любых -объекта:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "anyBefore",
        "rootFile",
        "anyAfter"
    })
    public static class RootFiles {

        @XmlAnyElement(lax = true)
        protected List<Object> anyBefore;
        @XmlElement(required = true)
        protected List<Container.RootFiles.RootFile> rootFile;
        @XmlAnyElement(lax = true)
        protected List<Object> anyAfter;

JavaDoc для XmlAnyElement говорит:

Эта аннотация является взаимоисключающей с XmlElement, XmlAttribute, XmlValue, XmlElements, XmlID и XmlIDREF.В классе и его суперклассах может быть только одно аннотированное свойство XmlAnyElement JavaBean.

Исходя из этого, я пришел к выводу, что JAXB на самом деле не заботится о втором @XmlAnyElement, а просто размещает всепрямые неизвестные в первое любое свойство.Я застрял в том, что делать.

Обратите внимание, что моя главная задача - сохранить неизвестные элементы в нужном месте (порядок, кажется, сохранен), меня не особо волнует их анализ,просто убедитесь, что они находятся в одном и том же месте при повторной сериализации XML после некоторых модификаций элементов .


Теперь вы можете задаться вопросом, почему я разработал бы такую ​​глупую схему, допускающую случайноеXML повсюду.К сожалению, это не моя вина, я просто пытаюсь вручную преобразовать эту схему RELAX NG из спецификаций Adobe UCF в схему XML , которую я могу использовать сJAXB.Проблема заключается в этой формулировке , которая разрешает любые внешние XML-элементы и атрибуты в META-INF / container.xml:

Соответствующие пользовательские агенты UCF ДОЛЖНЫ игнорировать нераспознанные элементы (и их содержимое).и нераспознанные атрибуты в файле container.xml, включая нераспознанные элементы и нераспознанные атрибуты из других пространств имен.

Соответствующие файлы container.xml ДОЛЖНЫ быть действительными в соответствии со схемой RELAX NG UCF с элементом в качестве корневого элемента после удалениявсе элементы (и дочерние узлы этих элементов) и атрибуты из других пространств имен.

Теперь я, конечно, мог бы просто удалить любые такие элементы, так как он говорит, что я могу их игнорировать, но я подумал, что если вБудущее или какое-то расширение они что-то значат, по крайней мере, я мог бы правильно сохранить такие элементы. Однако я нахожу это трудным, используя JAXB.

Есть ли какие-либо предложения о том, как мне этого добиться, например, некоторые магические свойства маршаллера/ Unmarshaller

1 Ответ

4 голосов
/ 24 ноября 2010

Вы можете объединить @XmlAnyElement с @XmlElementRef или @XmlElementRefs. Ваши аннотации будут выглядеть так:

@XmlElementRef(name="rootFile")
@XmlAnyElement
protected List<Object> beforeOrRootFileOrAfter;

В XML-схеме попробуйте <xs:choice maxOccurs="unbounded" .../>.

...