如何让XStream在解析XML时跳过未映射的标签?
我有一个大型 XML 文档,想要将其转换为 Java bean。它有很多标签和属性,但我只对其中的一小部分感兴趣。不幸的是,XStream 似乎强制您在该 bean 中为该 XML 中可能存在的每个标签声明一个属性。有办法解决这个问题吗?
I have a large XML document that I want to convert to a Java bean. It has a lot of tags and attributes, but I'm interested only in a handful of those. Unfurtounately, it seems that XStream forces you to declare a property in that bean for each and every tag that may ever be in that XML. Is there a way around this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如下所示初始化
XStream
以忽略 Bean 中未定义的字段。Initialize
XStream
as shown below to ignore fields that are not defined in your bean.XStream 1.4.5让您轻松处理未知标签。使用
ignoreUnknownElements()
对于尚未实现或已被删除的标签,并且您正在处理旧的 xml。您还可以指定要忽略的特定标签。XStream 1.4.5 makes you simple to deal with unknown tags. Use
ignoreUnknownElements()
for tags which are not implemented yet or has been removed and you are dealing with old xml. You can also specify which particular tag you would like to ignore.自 XStream 1.4.5 起,在编组器声明期间使用ignoreEnknownElements() 方法就足够了:
忽略不必要的元素。
Since XStream 1.4.5 durring marshaller declaration it's enough to use ignoreEnknownElements() method:
to ignore unnecessary elements.
我今天一直在解决这个问题,我发现使用
return this.realClass(fieldName) != null;
并不是(总是)一个可行的解决方案 然而实际上 XStream 有一种方法可以跳过未映射的标签并同时使用隐式集合。为什么
realClass(fieldName)
事情不起作用事实上,使用的技巧是
有效的。它的作用是尝试通过标签名称猜测类型,看看是否成功,如果不成功,则返回 false。因此,它会完美地跳过像
BUT 这样的标签,但它只会在某些“不需要的”标签碰巧有一个有意义的名称时起作用(!),而
realClass(fieldName )
实际上能够返回不等于null
的内容,并且该标记不会是您的任何 ImplicitCollection 的成员。在这种情况下,如果知道可以定义 xml 元素的类,并且用户类型 XStream 中没有映射此类字段,则将决定“也许该元素来自某个隐式集合”。如果你的类中既没有这样的集合,也没有这样的字段,它很快就会失败。就我而言,有问题的 xml 片段是这样的:当然,既没有
Url url;
也没有@XStreamImplicit List; url
在我的班级上。拥有这样的 XML 并使用“realClass”事物的结果如下:正确的方法
正确的方法是从
shouldSerializeMember
false > 如果defineIn == Object.class
(不使用realClass(fieldName)
东西)。但仅使用
return false
是不够的。在这种形式下,它将导致 XStream 将隐式集合留空。这里的技巧是确保使用
@XStreamImplicit(itemFieldName = "something")
而不是仅仅使用不带参数的@XStreamImplicit
,即使在标签名称和集合的情况下也是如此。通用参数类型具有相同的名称。因此,正确的代码将如下所示:
并且您需要确保在您的类中,您的隐式集合被标记为如下所示:
请注意,即使 List 的泛型类型参数具有相同的名称,
itemFieldName
也是显式指定的。这一点至关重要。在这种情况下,遇到
标签时,XStream 甚至不会使用该 fieldName 访问您的shouldSerializeMember
。它只是提前知道该元素来自隐式集合。当它再次遇到
http://somewhere.com
时将访问您的方法。但在这里我们是安全的,因为我们只是返回false
。对我有用!尝试一下。
I've been working my way around this problem today and what I've found out is that using
return this.realClass(fieldName) != null;
is not (always) a working solution however actually there is a way for XStream to skip unmapped tags AND work with implicit collections at the same time.Why
realClass(fieldName)
thing won't workIn fact trick with using
works. What it does is attempt to guess the type by the tag name, see whether it succeeded and if not - returns false. So it'll perfectly skip tags like
BUT it will work only up to the moment (!) when somehow some "not needed" tag will happen to have a meaningful name for which
realClass(fieldName)
will be actually able to return something not equal tonull
and that tag won't be a member of any ImplicitCollection of yours. In that case knowing that the class for an xml element could be defined and there is no such field mapped in users type XStream will decide that "maybe this element is from some implicit collection". And it will fail very soon if there is neither such collection nor a field in your class. In my case the problematic piece of xml was like this:and, of course, there was neither
Url url;
nor@XStreamImplicit List<Url> url
on my class. The result of having such an XML and using "realClass" thing is as follows:The right way
The right way would be returning plain
false
fromshouldSerializeMember
in case whendefinedIn == Object.class
(not usingrealClass(fieldName)
stuff).But just using
return false
alone is not enough. I this form it will cause XStream to leave implicit collections empty.The trick here is to make sure that one uses
@XStreamImplicit(itemFieldName = "something")
instead of just using@XStreamImplicit
without parameters even in the cases when tag name and collection's generic param type have the same name.So the right code will look like this:
And you need to be sure that in your classes your implicit collections are marked like this:
Notice that
itemFieldName
is explicitly specified even though List's generic type parameter has the same name. This is crucial.In this case upon encountering
<something>
tag XStream won't even visit yourshouldSerializeMember
with that fieldName. It will just know in advance that the element is from implicit collections.When it will visit your method is upon encountering
<url>http://somewhere.com</url>
again. But here we're safe since we just returnfalse
.Works for me! Give it a try.
在 XStream 实例中使用 ignoreUnknownElements() 方法:
Use ignoreUnknownElements() method in your XStream instance: