XStreamsignle集合中的几种节点类型

发布于 2024-12-15 04:16:52 字数 1053 浏览 0 评论 0原文

我正在尝试反序列化这样的 XML 文档:

<rootelem>
    <elementType1 arg1="..." />
    <elementType1 arg1="..." />
    <elementType1 arg1="..." />
    <elementType2 argA="..." argB="..." />
    <elementType2 argA="..." argB="..." />
    <elementType2 argA="..." argB="..." />
</rootelem>

默认情况下,XStream 只能解析这样的形式:

<rootelem>
    <list1>
        <elementType1 arg1="..." />
        <elementType1 arg1="..." />
        <elementType1 arg1="..." />
    </list1>

    <list2>
        <elementType2 argA="..." argB="..." />
        <elementType2 argA="..." argB="..." />
        <elementType2 argA="..." argB="..." />
    </list>
</rootelem>

这是因为 XStream 使用下一个格式的集合:

<collection>
    <elem .... />
    <elem .... />
    <elem .... />
</collection>

并且框架标签是强制性的。集合只能包含单一类型的节点。那么如何解析这样的XML文档呢?现在我已经为此编写了自己的转换器,但我想知道还有其他方法吗?

I'm trying to deserialize such XML document:

<rootelem>
    <elementType1 arg1="..." />
    <elementType1 arg1="..." />
    <elementType1 arg1="..." />
    <elementType2 argA="..." argB="..." />
    <elementType2 argA="..." argB="..." />
    <elementType2 argA="..." argB="..." />
</rootelem>

By default XStream can parse only such form:

<rootelem>
    <list1>
        <elementType1 arg1="..." />
        <elementType1 arg1="..." />
        <elementType1 arg1="..." />
    </list1>

    <list2>
        <elementType2 argA="..." argB="..." />
        <elementType2 argA="..." argB="..." />
        <elementType2 argA="..." argB="..." />
    </list>
</rootelem>

This is because XStream use next format for collections:

<collection>
    <elem .... />
    <elem .... />
    <elem .... />
</collection>

and frame tags are obligatory. Collection can contain only single type nodes. So how can I parse such XML document? Now I've written my own convertor for this but I wonder are there some other ways?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮烟 2024-12-22 04:16:52

我认为隐式集合是适合您的解决方案。

http://x-stream.github.io/alias-tutorial.html#implicit

这是示例代码:

package com.thoughtworks.xstream;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {

            Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
            teamBlog.add(new Entry("first","My first blog entry."));
            teamBlog.add(new Entry("tutorial",
                    "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));

            XStream xstream = new XStream();
            xstream.alias("blog", Blog.class);
            xstream.alias("entry", Entry.class);

            xstream.addImplicitCollection(Blog.class, "entries");

            System.out.println(xstream.toXML(teamBlog));
    }
}

结果:

<blog>
  <author>
     <name>Guilherme Silveira</name>
  </author>
  <entry>
     <title>first</title>
     <description>My first blog entry.</description>
  </entry>
  <entry>
     <title>tutorial</title>
     <description>
          Today we have developed a nice alias tutorial. Tell your friends! NOW!
     </description>
  </entry>
</blog>

I think that Implicit Collections is the solution for you.

http://x-stream.github.io/alias-tutorial.html#implicit

Here is the sample code:

package com.thoughtworks.xstream;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {

            Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
            teamBlog.add(new Entry("first","My first blog entry."));
            teamBlog.add(new Entry("tutorial",
                    "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));

            XStream xstream = new XStream();
            xstream.alias("blog", Blog.class);
            xstream.alias("entry", Entry.class);

            xstream.addImplicitCollection(Blog.class, "entries");

            System.out.println(xstream.toXML(teamBlog));
    }
}

And the result:

<blog>
  <author>
     <name>Guilherme Silveira</name>
  </author>
  <entry>
     <title>first</title>
     <description>My first blog entry.</description>
  </entry>
  <entry>
     <title>tutorial</title>
     <description>
          Today we have developed a nice alias tutorial. Tell your friends! NOW!
     </description>
  </entry>
</blog>
温柔女人霸气范 2024-12-22 04:16:52

您需要做的第一件事是为所有主要 XML 标记创建 POJO。我假设您给出的示例不是您需要“解组”的实际 XML(这是反序列化的 XML 术语),但为了给您提供一个示例,我将继续使用它;-)。

public class ElementType1
{
    private String arg1;

    public ElementType1()
    {
        setArg1("");
    }

    public String getArg1()
    {
        return arg1;
    }

    public void setArg1(String newArg1)
    {
        arg1 = newArg1;
    }
}

public class ElementType2
{
    private String argA;
    private String argB;

    public ElementType2()
    {
        setArgA("");
        setArgB("");
    }

    public String getArgA()
    {
        return argA;
    }

    public void setArgA(String newArgA)
    {
        argA = newArgA;
    }

    public String getArgB()
    {
        return argB;
    }

    public void setArgB(String newArgB)
    {
        argB = newArgB;
    }
}

public class RootElement
{
    private List<ElementType1> element1s;
    private List<ElementType2> element2s;

    public RootElement()
    {
        setElement1s(new ArrayList<ElementType1>());
        setElement2s(new ArrayList<ElementType2>());
    }

    public List<ElementType1> getElement1s()
    {
        return element1s;
    }

    public void setElement1s(List<ElementType1> newElement1s)
    {
        element1s = newElement1s;
    }

    public List<ElementType2> getElement2s()
    {
        return element2s;
    }

    public void setElement2s(List<ElementType2> newElement2s)
    {
        element2s = newElement2s;
    }   
}

现在您已经有了 POJO,使用 XStream 将它们编组(序列化)和反编组(反序列化)到 XML 或从 XML 中解编(反序列化)就非常容易了。

List<ElementType1> e1 = new ArrayList<ElementType1>();
List<ElementType2> e2 = new ArrayList<ElementType2>();

ElementType1 a, b, c;
a = new ElementType1();
b = new ElementType1();
c = new ElementType1();

a.setArg1("fizz");
b.setArg1("buzz");
c.setArg1("foo");

e1.add(a);
e1.add(b);
e1.add(c);

ElementType2 d, e;
d = new ElementType2();
e = new ElementType2();

d.setArgA("flim");
d.setArgB("flam");
e.setArgA("something");
e.setArgB("blah");

e2.add(d);
e2.add(e);

RootElement rootElem = new RootElement();
rootElem.setElement1s(e1);
rootElem.setElement2s(e2);

XStream xstream = new XStream();
RootElement rootElem = getYourRootElementSomehow();
String rootElementAsXml = xstream.toXML(rootElem);

System.out.println(rootElementAsXml);

此代码现在将在控制台上打印以下内容:

<fully.qualified.pkg.name.RootElement>
    <element1s>
        <fully.qualified.pkg.name.ElementType1>
            <arg1>fizz</arg1>
        </fully.qualified.pkg.name.ElementType1>
        <fully.qualified.pkg.name.ElementType1>
            <arg1>buzz</arg1>
        </fully.qualified.pkg.name.ElementType1>
        <fully.qualified.pkg.name.ElementType1>
            <arg1>foo</arg1>
        </fully.qualified.pkg.name.ElementType1>
    </element1s>
    <element2s>
        <fully.qualified.pkg.name.ElementType2>
            <argA>flim</argA>
            <argB>flam</argB>
        </fully.qualified.pkg.name.ElementType2>
        <fully.qualified.pkg.name.ElementType2>
            <argA>something</argA>
            <argB>blah</argB>
        </fully.qualified.pkg.name.ElementType2>
    </element2s>
</fully.qualified.pkg.name.RootElement>

然后,您可以使用 XStreams 多功能“别名”方法来清理名为 XML 元素的令人讨厌的完全限定包,如下所示:

xstream.alias("elementType1", ElementType1.class);
xstream.alias("elementType2", ElementType2.class);
xstream.alias("rootElement", RootElement.class);
String rootElementAsXml = xstream.toXML(rootElem);

System.out.println(rootElementAsXml);

现在将打印出:

<rootElement>
    <element1s>
        <elementType1>
            <arg1>fizz</arg1>
        </elementType1>
        <elementType1>
            <arg1>buzz</arg1>
        </elementType1>
        <elementType1>
            <arg1>foo</arg1>
        </elementType1>
    </element1s>
    <element2s>
        <elementType2>
            <argA>flim</argA>
            <argB>flam</argB>
        </elementType2>
        <elementType2>
            <argA>something</argA>
            <argB>blah</argB>
        </elementType2>
    </element2s>
</rootElement>

Now I know 在您的示例中,您希望所有 实际上都是 标记的属性 ,而不是子标签本身。您可以使用 XStream 强大的 API 来为您完成此操作,无论您喜欢什么。但希望这足以让您开始。

顺便说一句,将 XML 转换回 POJO 也同样简单:

RootElement root = (RootElement)xstream.fromXML(rootElementAsXml);

根据经验,XStream 是一个“oxmapper”(对象 XML 映射器),它是预先构建的,知道如何将 POJO 转换为有意义的 XML,反之亦然。您始终可以覆盖其默认设置,但更常见的是,我总是发现自己对其默认设置的智能程度感到惊讶。祝你好运。

The first thing you need to do is to create POJOs for all your major XML tags. I assume that the example you gave is not the actual XML you need to "unmarshall" (that's XML lingo for deserialization), but I'll roll with it for the sake of giving you an example to work off of ;-).

public class ElementType1
{
    private String arg1;

    public ElementType1()
    {
        setArg1("");
    }

    public String getArg1()
    {
        return arg1;
    }

    public void setArg1(String newArg1)
    {
        arg1 = newArg1;
    }
}

public class ElementType2
{
    private String argA;
    private String argB;

    public ElementType2()
    {
        setArgA("");
        setArgB("");
    }

    public String getArgA()
    {
        return argA;
    }

    public void setArgA(String newArgA)
    {
        argA = newArgA;
    }

    public String getArgB()
    {
        return argB;
    }

    public void setArgB(String newArgB)
    {
        argB = newArgB;
    }
}

public class RootElement
{
    private List<ElementType1> element1s;
    private List<ElementType2> element2s;

    public RootElement()
    {
        setElement1s(new ArrayList<ElementType1>());
        setElement2s(new ArrayList<ElementType2>());
    }

    public List<ElementType1> getElement1s()
    {
        return element1s;
    }

    public void setElement1s(List<ElementType1> newElement1s)
    {
        element1s = newElement1s;
    }

    public List<ElementType2> getElement2s()
    {
        return element2s;
    }

    public void setElement2s(List<ElementType2> newElement2s)
    {
        element2s = newElement2s;
    }   
}

Now that you have your POJOs, using XStream to marshall (serialize) and unmarshall (deserialize) them to and from XML is quite easy.

List<ElementType1> e1 = new ArrayList<ElementType1>();
List<ElementType2> e2 = new ArrayList<ElementType2>();

ElementType1 a, b, c;
a = new ElementType1();
b = new ElementType1();
c = new ElementType1();

a.setArg1("fizz");
b.setArg1("buzz");
c.setArg1("foo");

e1.add(a);
e1.add(b);
e1.add(c);

ElementType2 d, e;
d = new ElementType2();
e = new ElementType2();

d.setArgA("flim");
d.setArgB("flam");
e.setArgA("something");
e.setArgB("blah");

e2.add(d);
e2.add(e);

RootElement rootElem = new RootElement();
rootElem.setElement1s(e1);
rootElem.setElement2s(e2);

XStream xstream = new XStream();
RootElement rootElem = getYourRootElementSomehow();
String rootElementAsXml = xstream.toXML(rootElem);

System.out.println(rootElementAsXml);

This code will now print the following to the console:

<fully.qualified.pkg.name.RootElement>
    <element1s>
        <fully.qualified.pkg.name.ElementType1>
            <arg1>fizz</arg1>
        </fully.qualified.pkg.name.ElementType1>
        <fully.qualified.pkg.name.ElementType1>
            <arg1>buzz</arg1>
        </fully.qualified.pkg.name.ElementType1>
        <fully.qualified.pkg.name.ElementType1>
            <arg1>foo</arg1>
        </fully.qualified.pkg.name.ElementType1>
    </element1s>
    <element2s>
        <fully.qualified.pkg.name.ElementType2>
            <argA>flim</argA>
            <argB>flam</argB>
        </fully.qualified.pkg.name.ElementType2>
        <fully.qualified.pkg.name.ElementType2>
            <argA>something</argA>
            <argB>blah</argB>
        </fully.qualified.pkg.name.ElementType2>
    </element2s>
</fully.qualified.pkg.name.RootElement>

You can then clean up the nasty, fully-qualified package named XML elements by using XStreams versatile "alias" methods, like so:

xstream.alias("elementType1", ElementType1.class);
xstream.alias("elementType2", ElementType2.class);
xstream.alias("rootElement", RootElement.class);
String rootElementAsXml = xstream.toXML(rootElem);

System.out.println(rootElementAsXml);

Which will now print out:

<rootElement>
    <element1s>
        <elementType1>
            <arg1>fizz</arg1>
        </elementType1>
        <elementType1>
            <arg1>buzz</arg1>
        </elementType1>
        <elementType1>
            <arg1>foo</arg1>
        </elementType1>
    </element1s>
    <element2s>
        <elementType2>
            <argA>flim</argA>
            <argB>flam</argB>
        </elementType2>
        <elementType2>
            <argA>something</argA>
            <argB>blah</argB>
        </elementType2>
    </element2s>
</rootElement>

Now I know that in your example, you wanted all the <arg>s to actually be attributes of the <elementType> tags, not child tags themselves. You can use XStream's powerful API to do this for you, however you like. But hopefully this is enough to get you started.

And by the way, turning your XML back into a POJO is just as easy:

RootElement root = (RootElement)xstream.fromXML(rootElementAsXml);

As a rule of thumb, XStream is an "oxmapper" (Object-XML Mapper), and it come pre-built to know how to turn your POJO into meaningful XML and vice versa. You can always override its defaults, but more often then not I have always found myself surprised with how smart its defaults are. Best of luck to you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文