我有一个场景,我必须读取这样的xml:
<MovieList language="English">
<Movie>..<Movie>
<Movie>..<Movie>
</MovieList>
我必须阅读电影标签,这是一个复杂的对象(标签),并将细节插入电影表。我已将fragmentRootElementName设置为Movie,并且能够完全读取Movie标签。但是,我无法读取语言属性,这不是重复标记。
我应该如何获取不重复的标签详细信息?我应该自己解析XML来阅读吗?或者我应该再写一个fragmentRootElementName来读取语言属性吗?
项目阅读器的配置如下:
<bean id="movieReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="unmarshaller" ref="marshaller" />
<property name="fragmentRootElementName" value="Movie" />
<property name="resource" value="file:#{jobParameters['inputFile']}" />
</bean>
答案 0 :(得分:2)
好的,简单的方法是定义你的fragmentRootElementName = MovieList,但我想如果你的MovieList可以包含数百万部电影,这不是一个好主意!
我有一个类似的问题,我需要知道我的fragmentRootElementName的父标签。
因此我们创建了一个CustomStaxEventItemReader,它扩展了原始的StaxEventItemReader。
我们添加了您可以在配置中设置的属性parentElement。并且我们重写方法moveCursorToNextFragment()和doRead()以便能够处理这个问题!
现在代码我没有完全按照您的需要做,但我修改了它看起来好像有效!!!
protected boolean moveCursorToNextFragment(XMLEventReader reader) {
try {
while (true) {
while (reader.peek() != null && !reader.peek().isStartElement()) {
reader.nextEvent();
}
if (reader.peek() == null) {
return false;
}
XMLEvent ev = reader.peek();
QName startElementName = ((StartElement) ev).getName();
// Take note of current parent element. Must be one of
// ParentTags
String tmp = startElementName.getLocalPart();
for (ParentTags aTag : ParentTags.values()) {
if (aTag.toString().equals(tmp)) {
currentParent = tmp;
Attribute attr = ((StartElement) ev)
.getAttributeByName(new QName("Language"));
if (null != attr) {
parentAttribute = attr.getValue();
}
break;
}
}
if (startElementName.getLocalPart().equals(
fragmentRootElementName)) {
if ((fragmentRootElementNameSpace == null && parentElement
.equals(currentParent))
|| startElementName.getNamespaceURI().equals(
fragmentRootElementNameSpace)) {
return true;
}
}
reader.nextEvent();
}
} catch (XMLStreamException e) {
throw new DataAccessResourceFailureException(
"Error while reading from event reader", e);
}
}
所以基本上,如果你查看原始StaxEventReader的代码,你会看到它通过xml文件的所有元素。每当它获得一个名为=你的rootElement的元素时,它返回true并且doRead解组它并返回相关的对象。
现在,我们只添加一些代码来查找给定的父元素。我使用了名为ParentTags的Enum,因为我的XML更复杂,但您只能比较配置中定义的新parentElement的名称。
因此,如果实际元素isEquals到您的parentElement,您只需将其分配给currentParent并尝试获取您的属性。如果不为null,则将其分配给parentAttribute属性。
然后在你的doRead()方法中,你可以访问parentAttribute属性并在你的域对象中设置它!
protected T doRead() throws Exception {
if (noInput) {
return null;
}
T item = null;
if (moveCursorToNextFragment(fragmentReader)) {
fragmentReader.markStartFragment();
@SuppressWarnings("unchecked")
T mappedFragment = (T) unmarshaller.unmarshal(StaxUtils
.createStaxSource(fragmentReader));
item = mappedFragment;
logger.info("Item read : " + item);
currentIndex = cIndex.getAndIncrement();
T p = (T) item;
if (p instanceof myDomainObj) {
myDomainObj pp = (myDomainObj) p;
logger.info(pp);
logger.info("attribute parent = " + parentAttribute);
pp.setLanguage(parentAttribute);
}
fragmentReader.markFragmentProcessed();
}
return item;
}
我希望这很清楚!
祝你好运和问候