将 XML 结构解析为一组简单、通用的映射和列表
与如何将 XML 转换为 java 有点相关。 util.Map ,反之亦然,只是更通用。
我有一个 XML 文档,我想将其转换为一组非常通用的键/值对(即 Java 中的键/值对)。基本思想是我们可以解析几乎每个 XML 文档并将其直接传递到 JSP 文件,该文件可以读取值并显示它们。
假设有一个 XML 结构如下:
<root>
<items>
<item id="10">Some item here</item>
</items>
<things>
<thing awesome="true">
<orly-owl hoot="woot" />
</thing>
</things>
</root>
输出将是一组 Map 对象,其中都包含值、列表和其他映射。理想情况下,它是如何在(伪)JSP 文件中读取的:
<c:forEach var="item" items="${root.items}">
${item.id}
${item.text}
</c:forEach>
<c:forEach var="things" items="${root.things}">
Is it awesome? ${thing.awesome}
orly? ${thing.orly-owl.hoot}
</c:forEach>
基本上,它是一个具有一组简单规则的 xml 解析器。
对于每个 XML 实体:
它是否有子节点?
向映射添加条目,以节点名称作为键,以(映射的)列表作为值 它有属性或价值吗? 添加条目到映射,属性名称作为键,属性值作为值
......或某种程度的东西。我还没有真正正确地考虑数据结构。
所以我的问题是:是否有一个现成的解析器可以执行此操作或类似的操作?
我今天发现并尝试过的所有对象都映射到固定的对象层次结构,即您必须使用具有自己属性的 Item 对象列表创建根对象。这本身并不坏(并且它可以基于(要编写/设计的)DTD 对象自动生成,但我当前的任务是尝试这两个选项。尝试了第一个,一旦这些映射它就会工作xml 文件对我来说很有意义,错误消息开始告诉我我做错了什么,但一直无法弄清楚如何执行第二个操作(阅读:编写一个递归的递归 xml 解析器(dom 或 sax)) 这个问题可能缺乏一致性,
现在是五点钟,
经过更多思考后它会起作用(即将包含值、映射和列表的对象发送到 JSP)。解析时会出现严重问题,例如在下一个示例中:
<root thing="thine mother">
<thing mabob="yus" />
<thing mabob="nay" />
<items>
<item id=1" />
</items>
</root>
在这个特定实例中,根下有两个同名的元素元素应该进入列表。但是,在同一级别有一个 items 元素,这是一个单一元素,应该作为地图项添加到根元素中还有第三个名为“元素”的元素,整个事情都被搞砸了。
如果没有事先分析结构(并设置一个标志,例如“在这个特定元素下既有同名元素又有唯一命名元素”),您就不能假设这一点。我想做的最后一件事是强制 XML 符合特定的结构。
我的同事实际上建议通过 XSL 运行 XML,以便它“更扁平”(更像数据库行),或者让 xml 输出的最大深度为 1。真的不是一个选择。
无论如何。感谢大家的建议,看来这不是一个非常合理的问题解决方案 - 至少不会搞乱 XML 和常识的基本规则和约定。
接下来的想法 - 让 JSP 使用 XML JSTL 库直接呈现文档。
Somewhat related to How to convert XML to java.util.Map and vice versa, only even more generic.
I have an XML document, and I'd like to convert it to a very generic set of key/value pairs (in Java, that is). The basic idea is that we can parse pretty much every XML document and pass it on directly to a JSP file, which can read the values and display them.
Say one has an XML structure as follows:
<root>
<items>
<item id="10">Some item here</item>
</items>
<things>
<thing awesome="true">
<orly-owl hoot="woot" />
</thing>
</things>
</root>
The output would be a set of Map objects that both contain values, lists, and other maps. Here's how, ideally, it'd be read in a (pseudo) JSP file:
<c:forEach var="item" items="${root.items}">
${item.id}
${item.text}
</c:forEach>
<c:forEach var="things" items="${root.things}">
Is it awesome? ${thing.awesome}
orly? ${thing.orly-owl.hoot}
</c:forEach>
Basically, it'd be an xml parser of sorts that has a simple set of rules.
For each XML entity:
Does it have subnodes?
add entry to map with node name as key and List (of maps) as value
Does it have attributes or value?
add entry to map with attribute name as key and attribute value as value
...or something to that degree. I don't really have the data structure in mind properly yet.
So my question is: Is there a ready-made parser that can do this or something like this?
The ones I've found and tried out today all map to a fixed object hierarchy, i.e. you have to create a root object with a List of Item objects with its own properties. This isn't bad per sé (and it can be auto-generated based on a (to be written / designed) DTD object, but it's my current assignment to try out both options. Tried the first, it'll work once those mapping xml files make sense to me and error messages start telling me what I'm doing wrong, but haven't been able to figure out how to do the second (read: write a recursive xml parser (dom or sax) that recurses recursively).
Coherency may be absent in this question, it's five 'o clock.
Edit, after thinking it through some more. It will work (that is, sending Objects to JSP that can contain values, Maps and Lists), however it'll be terribly problematic while parsing, for example in the next example:
<root thing="thine mother">
<thing mabob="yus" />
<thing mabob="nay" />
<items>
<item id=1" />
</items>
</root>
In this particular instance, there's two same-named thing-elements under the root. Same-named elements should go into a List. However, at the same level there's an items element, which is a singular element which should go in as a map item. Add to that there's a third named 'element' in the root element, and the whole thing's buggered.
Without analyzing the structure beforehand (and setting a flag like 'there's both same-named and unique-named elements under this particular element'), you cannot assume this. And the last thing I want to do is to force the XML to be according to a particular structure.
My colleague actually suggested running the XML through an XSL so that it'd be 'flatter' (more like database rows), or having the xml output have a maximum depth of one. Not an option, really.
Anyways. Thanks for the suggestions all, it seems this isn't a very plausible solution to the problem - at least not without screwing up basic rules and conventions of XML and Common Sense.
On to the next ideas - having JSP render a Document directly using the XML JSTL library.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
JDOM 当然可以为您提供从元素构建的列表。该库已经存在相当长一段时间了,并且非常易于使用。 http://jdom.org/
JDOM can certainly provide you with Lists built from the elements. The library has been around for quite some time and is pretty easy to use. http://jdom.org/
似乎 JSTL XML 绑定 将完全满足您的需求。
使用列表和映射不太可能找到完全满足您要求的任何内容的原因是 XML 不能巧妙地转换为列表和映射(主要是因为“您如何以不同于内容的方式对待属性?”)。
It seems like the JSTL XML bindings will do exactly what you want.
And the reason that you're unlikely to find anything that exactly meets your requirements using lists and maps is because XML does not neatly translate into lists and maps (mostly because of the question "how do you treat attributes differently than content?").
Java Architecture for XML Binding (JAXB) 应该适合您列表。这是一个简介 教程介绍。
Java Architecture for XML Binding (JAXB) should be on your short list. Here's a bief tutorial introduction.
apache-commons Digester 可以做到这一点,它是 SAX 解析器的包装器,可让您创建将数据解组为对象的规则。
OTOH如果您想知道如何进行递归解析,您可以查看 这篇文章提供了一种有趣的方法(使用递归转换网络)。这个想法是,您创建一个对象网络来显示 xml 元素之间的关系,并在使用堆栈进行解析时跟踪您在该网络中的位置。
The apache-commons Digester could do this, it is a wrapper around a SAX parser that lets you create rules for unmarshalling data into objects.
OTOH if you want to know how to do recursive parsing you could check out this article for an interesting approach (using a recursive transition network). The idea is you create a network of objects that shows the relationship between the xml elements, and you keep track of where you are in this network as you parse using a stack.