XStream:在我解析时折叠XML层次结构 [英] XStream: Collapsing XML hierarchy as I parse

查看:165
本文介绍了XStream:在我解析时折叠XML层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个XML文档(由Adobe XFA表单生成),其中包含如下数据:

I have an XML document (generated by Adobe XFA forms), that contains data like the following:

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

由于此文件在其他地方定义,我无权自行更改我得到的XML格式。

Since this file is defined elsewhere, I am not at liberty to change the format of the XML that I get.

在我的Java代码中,我创建了一个包含标题,开始和结束日期的Position类。

In my Java code, I create a Position class that contains the Title, Start and End Dates.

我的问题是,当我使用XStream解析文件时,它需要一个PositionBorder类来保存标题和日期。我想基本上忽略边框并将所有字段放入Position类。

My problem is, when I use XStream to parse the file, it wants a PositionBorder class to hold the title and dates. I want to basically ignore the border and place all of the fields into the Position class.

我真正想做的是使用convertAnother方法之类的东西进行转换位置元素的子元素。我试图这样做但它失败了,因为我的PositionConverter被调用了PositionBorder(当我调用convertAnother时)。

What I'd really like to do is use something like the convertAnother method to convert the child of the position element. I tried to do just that and it fails, because my PositionConverter gets called for the PositionBorder (when I call convertAnother).

任何人都有任何线索如何处理崩溃解析时XML的结构?

Anyone have any clues how to deal with collapsing the structure of an XML when parsing?

推荐答案

使用自定义转换器并不是非常困难。这是一个很长的例子,但我希望它很简单,可以得到你需要做的事情:

It's not terribly difficult to do with a custom converter. This is a little bit of a long example, but I hope it's simple enough to get the gist of what you need to do:

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类也没有嵌套),但是从String转换到一个日期(或其他什么)应该是相当微不足道的。

Try running that and see what happens. You'll need to modify it to suit your own types, of course -- I just used strings for all of Position's fields (and I'm sure you're Position class isn't nested, either), but converting from a String to a Date (or whatever) should be rather trivial.

你要注意的一件事(我可能没有完全理解它 在我的示例中)与您的reader.moveDown()和reader.moveUp()调用匹配。 (并且,如果你打算进行任何编组而不仅仅是解组 - 我不希望你的问题 - 你也想要匹配你的writer.startNode()和writer.endNode()调用。)这个例子可能不会引起任何问题,但我相信如果你做的更大或使用相同的XStream或Converter实例处理多个文件会引发问题。此外,如果你从一个无效的位置尝试reader.moveDown(),你会得到一个非常丑陋的例外 - 它应该是非常明显的。

One thing you'll want to keep an eye on (and I might not have gotten it completely right in my example) is matching your reader.moveDown() and reader.moveUp() calls. (And, if you're going to do any marshalling instead of just unmarshalling -- which I don't expect from your question -- you'll want to match your writer.startNode() and writer.endNode() calls as well.) It probably won't cause any problems with this example, but I'm sure it'll raise issues if you're doing anything larger or processing multiple files with the same XStream or Converter instance. Also, if you try reader.moveDown() from an invalid location, you'll get a really ugly exception -- it should be pretty obvious.

我不得不使用moveUp / moveDown方法来使它们在正确的位置,所以我相信你需要测试它并调整直到你得到你需要的东西。

I had to play around with the moveUp/moveDown methods a bit to get them in the right places, so I'm sure you'll need to test it and tweak it until you get what you need.

这篇关于XStream:在我解析时折叠XML层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆