2

私は持っている

@XmlRootElement(namespace = "http://www.w3.org/2005/Atom", name = "content")
@XmlType(name = "course")
public class Course implements Resource

...

@XmlElementWrapper(name="subcourses")
@XmlElement(name="course")
List<Xlink> subcourses;         //!?

インライン変数で正常に動作する Xlink クラス。

public class Xlink
{
    private String href;
    private String value;

    @XmlAttribute(namespace = "http://www.w3.org/1999/xlink")
    public String getHref()
    {
        return href;
    }

    public void setHref(String href)
    {
        this.href = href;
    }

    @XmlValue
    public String getValue()
    {
        return value;
    }

    public void setValue(String value)
    {
        this.value = value;
    }
}

の XML 入力の場合

<atom:content atom:type="xml" xsi:type="course">
...
   <subcourses>
      <course xlink:href="course1">Some course</course>
      <course xlink:href="course2">other course</course>

また、サブコースは非整列化を拒否します (例外がスローされることなく)。

注: 残念ながら、MOXy はオプションではありません。

編集:新しいマーシャリングされたオブジェクト

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:content xmlns:ns2="http://www.w3.org/1999/xlink" xmlns:ns3="http://www.w3.org/2005/Atom">
    <code>SOME CODE</code>
    <name>name</name>
    <subcourses>
        <course ns2:href="Some href">some value</course>
        <course ns2:href="sdsdg">sdfhdfhdhdh</course>
    </subcourses>
</ns3:content>

Edit2:テストオブジェクトのアンマーシャリングとマーシャリングに関するいくつかの実験の後、コンテンツのヘッダーにxmlns名前空間を定義して一致させる必要があることを発見しましxlink:href=xmlns:xlink="http://www.w3.org/1999/xlink"。問題は、解析されたラッパークラス内から Course 要素を取得していることです。安心して。したがって、結果のクラスは名前空間情報を継承しません。

どうにかしてJAXBにそれがコース要素に当てはまることを理解させる必要がありますxmlns:xlink="http://www.w3.org/1999/xlink"が、1時間のグーグルの後、私は途方に暮れています.

Edit3:オブジェクトを取得しています

https://github.com/jirutka/atom-jaxb/blob/master/src/main/java/cz/jirutka/atom/jaxb/Entry.java

サーバー側で使用されます。次に、これはの一部です

https://github.com/jirutka/atom-jaxb/blob/master/src/main/java/cz/jirutka/atom/jaxb/Feed.java

私の非整列化コードの関連部分は次のとおりです。

Feed f = r.readEntity(Feed.class);
out.addAll(unmarshaller.Unmarshal(f.getEntries(), clazz));

はどこrですかjavax.ws.rs.core.Response。そして、アンマーシャラー

public List<T> Unmarshal(List<Entry> entries, Class clazz)
{
    List<T> out = new ArrayList<T>();
    T instance;
    for (Entry e : entries)
    {
        try
        {
            JAXBContext context = JAXBContext.newInstance(clazz);
            Unmarshaller unmarsh = context.createUnmarshaller();
            instance = (T) unmarsh.unmarshal((Node) e.getContent());

これはこのテクノロジーとの最初のもつれであるため、このコードが「wtf」である可能性は十分にあります。

4

1 に答える 1

8

フィールド (インスタンス変数) に注釈を付けるときは、必ず@XmlAccessorType(XmlAccessType.FIELD)クラスに配置してください。

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement(namespace = "http://www.w3.org/2005/Atom", name = "content")
@XmlAccessorType(XmlAccessType.FIELD)
public class Course implements Resource {

    @XmlElementWrapper(name = "subcourses")
    @XmlElement(name = "course")
    List<Xlink> subcourses;

}

次に、XML 入力が名前空間で正しく修飾されていることを確認してください。入力ドキュメントは次のようになります。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<atom:content xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:atom="http://www.w3.org/2005/Atom">
    <code>SOME CODE</code>
    <name>name</name>
    <subcourses>
        <course xlink:href="Some href">some value</course>
        <course xlink:href="sdsdg">sdfhdfhdhdh</course>
    </subcourses>
</atom:content>

私の更新されたCourseクラス、あなたのXlinkクラス、および適切に名前空間修飾された XML ドキュメントを使用すると、次のデモ コードが完全に機能しました。

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Course.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum17766166/input.xml");
        Course course = (Course) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(course, System.out);
    }

}

更新 #1

Edit2: テスト オブジェクトのアンマーシャリングとマーシャリングをいくつか実験した後、コンテンツのヘッダーに xmlns 名前空間を定義して、xlink:href= のように xmlns:xlink="http://www.w3.org/ と一致させる必要があることを発見しました。 1999/xlink」の問題は、resteasy によって解析されるラッパー クラス内から Course 要素を取得していることです。したがって、結果のクラスは名前空間情報を継承しません。

問題を修正するのに最適な場所は、非整列化したいフラグメントを抽出する場所です。以下は、StAX で使用できる戦略です。

入力.xml

以下は、非整列化するフラグメントの上に名前空間情報が定義されている XML ドキュメントのサンプルです。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:atom="http://www.w3.org/2005/Atom">
    <bar>
        <atom:content>
            <code>SOME CODE</code>
            <name>name</name>
            <subcourses>
                <course xlink:href="Some href">some value</course>
                <course xlink:href="sdsdg">sdfhdfhdhdh</course>
            </subcourses>
        </atom:content>
    </bar>
</foo>

デモ

以下では、StAXXMLStreamReaderを使用してターゲット フラグメントに移動します。JAXB 実装でこのフラグメントを非整列化します。このようにして、すべての名前空間情報が保持されます。

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Course.class);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource source = new StreamSource("src/forum17766166/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(source);
        while(xsr.hasNext()) {
            if(xsr.isStartElement() && "content".equals(xsr.getLocalName())) {
                break;
            }
            xsr.next();
        }

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Course course = (Course) unmarshaller.unmarshal(xsr);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(course, System.out);
    }

}

出力

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:content xmlns:ns2="http://www.w3.org/1999/xlink" xmlns:ns3="http://www.w3.org/2005/Atom">
    <subcourses>
        <course ns2:href="Some href">some value</course>
        <course ns2:href="sdsdg">sdfhdfhdhdh</course>
    </subcourses>
</ns3:content>

更新 #2

UPDATE #1 で説明されているように、より良い XML フラグメントを生成できない場合は、現在の XML フラグメントを修正する方法を以下に示します。

NamespaceFilter

SAXXMLFilterを使用して XML 文書を修正できます。

import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class NamespaceFilter extends XMLFilterImpl {

    private static final String ATOM_URI = "http://www.w3.org/2005/Atom";
    private static final String XLINK_URI = "http://www.w3.org/1999/xlink";

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        if("atom:content".equals(qName)) {
            super.startElement(ATOM_URI, "content", qName, atts);
        } else if("course".equals(qName))  {
            AttributesImpl modifiedAtts = new AttributesImpl();
            modifiedAtts.addAttribute(XLINK_URI, "href", "xlink:href", null, atts.getValue(0));
            super.startElement(uri, localName, qName, modifiedAtts);
        } else {
            super.startElement(uri, localName, qName, atts);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if("atom:content".equals(qName)) {
            super.endElement(ATOM_URI, "content", qName);
        } else {
            super.endElement(uri, localName, qName);
        }
    }

}

デモ

XmlFilter以下は、JAXB でを活用する方法です。

import javax.xml.bind.*;
import javax.xml.parsers.*;
import org.xml.sax.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Course.class);

        // Create the XMLFilter
        XMLFilter filter = new NamespaceFilter();

        // Set the parent XMLReader on the XMLFilter
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        filter.setParent(xr);

        // Set UnmarshallerHandler as ContentHandler on XMLFilter
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        UnmarshallerHandler unmarshallerHandler = unmarshaller
                .getUnmarshallerHandler();
        filter.setContentHandler(unmarshallerHandler);

        // Parse the XML
        InputSource xml = new InputSource("src/forum17766166/input.xml");
        filter.parse(xml);
        Course course = (Course) unmarshallerHandler.getResult();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(course, System.out);
    }

}

詳細については


更新 #3

以下は、すべてが機能するコード例の簡略化されたバージョンです。たぶん、あなたのコードには何か違うものがあり、見つけるのに役立つでしょう.

エントリ

import javax.xml.bind.annotation.*;

@XmlRootElement(namespace="http://www.w3.org/2005/Atom")
@XmlAccessorType(XmlAccessType.FIELD)
public class Entry<T> {

    @XmlElement(namespace = "http://www.w3.org/2005/Atom")
    @XmlSchemaType(name = "atomInlineOtherContent")
    private T content;

    public T getContent() {
        return content;
    }

}

入力.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<atom:entry xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:atom="http://www.w3.org/2005/Atom">
    <atom:content>
        <code>SOME CODE</code>
        <name>name</name>
        <subcourses>
            <course xlink:href="Some href">some value</course>
            <course xlink:href="sdsdg">sdfhdfhdhdh</course>
        </subcourses>
    </atom:content>
</atom:entry>

デモ

import java.io.File;
import javax.xml.bind.*;
import org.w3c.dom.Node;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Entry.class, Course.class);

        // Unmarshal Entry
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum17766166/input.xml");
        Entry entry = (Entry) unmarshaller.unmarshal(xml);

        // Unmarshal Course
        Node contentNode = (Node) entry.getContent();
        Course course = (Course) unmarshaller.unmarshal(contentNode);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(course, System.out);
    }

}

出力

<?xml version="1.0" encoding="UTF-8"?>
<ns0:content xmlns:ns1="http://www.w3.org/1999/xlink" xmlns:ns0="http://www.w3.org/2005/Atom">
   <subcourses>
      <course ns1:href="Some href">some value</course>
      <course ns1:href="sdsdg">sdfhdfhdhdh</course>
   </subcourses>
</ns0:content>
于 2013-07-20T22:42:54.217 に答える