6

次のようなデータを含むXMLドキュメント(Adobe XFAフォームによって生成された)があります。

<Position>
   <PositionBorder>
       <Title/>
       <StartDate/>
       <EndDate/>
   </PositionBorder>
</Position>

このファイルは他の場所で定義されているため、取得したXMLの形式を自由に変更することはできません。

私のJavaコードでは、タイトル、開始日、終了日を含むPositionクラスを作成します。

私の問題は、XStreamを使用してファイルを解析するときに、PositionBorderクラスがタイトルと日付を保持する必要があることです。基本的に境界線を無視して、すべてのフィールドをPositionクラスに配置します。

私が本当にやりたいのは、convertAnotherメソッドのようなものを使用してposition要素の子を変換することです。私はそれをやろうとしましたが、PositionConverterがPositionBorderに対して呼び出されるため(convertAnotherを呼び出すと)失敗します。

解析時にXMLの構造が崩壊することに対処する方法を知っている人はいますか?

4

2 に答える 2

4

カスタムコンバーターを使用することはそれほど難しくありません。これは少し長い例ですが、必要なことの要点を理解するのに十分簡単であることを願っています。

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public final class ConverterTest {
    public static void main(String[] args) {
        XStream xstream = new XStream();
        xstream.autodetectAnnotations(true);
        xstream.registerConverter(new PositionConverter());

        final Position position = new Position();
        position.setTitle("The Title");
        position.setStartDate("The Start Date");
        position.setEndDate("The End Date");

        final String xml = xstream.toXML(position);
        System.out.println("Generated XML:");
        System.out.println(xml);

        final Position genPosition = (Position) xstream.fromXML(xml);
        System.out.println("Generated Position:");
        System.out.println("\tTitle: " + genPosition.getTitle());
        System.out.println("\tStart Date: " + genPosition.getStartDate());
        System.out.println("\tEnd Date: " + genPosition.getEndDate());
    }

    @XStreamAlias("Position")
    private static class Position {
        public String getEndDate() {
            return endDate;
        }

        public void setEndDate(String endDate) {
            this.endDate = endDate;
        }

        public String getStartDate() {
            return startDate;
        }

        public void setStartDate(String startDate) {
            this.startDate = startDate;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        private String title;
        private String startDate;
        private String endDate;
    }

    private static class PositionConverter implements Converter {
        public boolean canConvert(Class clazz) {
            return Position.class == clazz;
        }

        public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
            Position position = (Position)value;
            writer.startNode("PositionBorder");

            writer.startNode("Title");
            writer.setValue(position.getTitle());
            writer.endNode();

            writer.startNode("StartDate");
            writer.setValue(position.getStartDate());
            writer.endNode();

            writer.startNode("EndDate");
            writer.setValue(position.getEndDate());
            writer.endNode();

            writer.endNode();
        }

        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            Position position = new Position();
            // move it to <PositionBorder> tag.
            reader.moveDown();
            // now move it to <Title> tag.
            reader.moveDown();
            String title = reader.getValue();
            position.setTitle(title);
            reader.moveUp(); // moves back to <PositionBorder>

            reader.moveDown(); // should move down to <StartDate> tag
            String startDate = reader.getValue();
            position.setStartDate(startDate);
            reader.moveUp(); // move back to <PositionBorder>

            reader.moveDown(); // should move down to <EndDate> tag
            String endDate = reader.getValue();
            position.setEndDate(endDate);
            reader.moveUp(); // move back to <PositionBorder>


            return position;
        }
    }
}

それを実行してみて、何が起こるかを確認してください。もちろん、独自のタイプに合わせて変更する必要があります。私は、Positionのすべてのフィールドに文字列を使用しましたが(Positionクラスもネストされていないことは確かです)、文字列から変換します。日付(または何でも)にかなり些細なはずです。

注目したいことの1つは(私の例では完全に正しく理解できていない可能性があります)、reader.moveDown()呼び出しとreader.moveUp()呼び出しを一致させることです。(そして、マーシャリングを解除するだけでなく、マーシャリングを行う場合は、質問からは予想していませんが、writer.startNode()とwriter.endNode()の呼び出しも一致させる必要があります。 。)この例ではおそらく問題は発生しませんが、同じXStreamまたはConverterインスタンスで何か大きなことをしたり、複数のファイルを処理したりすると、問題が発生することは間違いありません。また、無効な場所からreader.moveDown()を試してみると、非常に醜い例外が発生します。これは非常に明白なはずです。

moveUp / moveDownメソッドを少し試して適切な場所に配置する必要があったので、必要なものが得られるまでテストして微調整する必要があると確信しています。

于 2010-02-23T23:55:37.107 に答える
0

私はこの方法がより使いやすいと思います:

@Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        Position mPosition = new Position();
        while (reader.hasMoreChildren()) {

            reader.moveDown();

            String nodeName = reader.getNodeName();

            if ("Title".equalsIgnoreCase(nodeName)) {
                mPosition.setTitle(reader.getValue());
            } else if ("StartDate".equalsIgnoreCase(nodeName)) {
                mPosition.setStartDate(reader.getValue());
            }else if ("attributeexample".equalsIgnoreCase(nodeName)) {
                mPosition.setAttributeExample(reader.getAttribute("attrname"));
            }

            reader.moveUp();
        }

        return mPosition;
    }
于 2010-11-12T19:55:34.150 に答える