【问题标题】:How to get value of xml element by using xml tags in HierarchicalStreamReader converter如何在 HierarchicalStreamReader 转换器中使用 xml 标签获取 xml 元素的值
【发布时间】:2019-06-20 11:46:25
【问题描述】:

我正在尝试使用 Spring Batch 将 XML 解析为 Java 对象,并且我正在使用 HierarchicalStreamReader 作为转换器来解析对象值并将其从 XML 标记转换为我的 POJO 字段。但是,在转换时,我必须使用 moveup() 和 moveDown() 方法来解析数据,我认为这不是一个好的做法,因为如果 XML 标记中的字段位置发生更改,则会导致代码重写。我已经尝试过 getAttribute(String name) 方法来实现对我试图通过使用其标签名称获取的参数的更多控制,但它给了我无法修复的错误。

此外,没有为界面提供足够的文档。请帮助我解决这个问题或建议我一些控制转换器的方法。提前谢谢...

Student.xml

<students>
    <student>
        <name>Tony Tester</name>
        <rollNo>1</rollNo>
        <enrollmentDate>2016-10-31</enrollmentDate>
        <sampleTimeStamp>2016-11-07T05:50:45</sampleTimeStamp>
        <salary>16.57</salary>
    </student>
    <student>
        <name>Nick Newbie</name>
        <rollNo>2</rollNo>
        <enrollmentDate>2017-10-31</enrollmentDate>
        <sampleTimeStamp>2016-11-07T05:50:45</sampleTimeStamp>
        <salary>29.68</salary>
    </student>
    <student>
        <name>Ian Intermediate</name>
        <rollNo>3</rollNo>
        <enrollmentDate>2018-10-31</enrollmentDate>
        <sampleTimeStamp>2016-11-07T05:50:45</sampleTimeStamp>
        <salary>789.62</salary>
    </student>
</students>

StudentDTO.java

@XmlRootElement(name="student")
public class StudentDTO 
{
    private String name;
    private Integer rollNo;    
    private Date enrollmentDate;
    private Date sampleTimeStamp;
    private BigDecimal salary;
    ... getter, setter and constructor
}

StudentConverter.java

public class StudentConverter implements Converter
{

    @Override
    public boolean canConvert(@SuppressWarnings("rawtypes") Class type) 
    {
        return type.equals(StudentDTO.class);
    }

    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) 
    {
        // Nothing to marshal
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) 
    {
        //reader.getAttribute(0) -- line causing error
                //reader.getAttribute("name") -- return null
                //reader.getAttributeCount() -- always return 0
        reader.moveDown();      
        StudentDTO student = new StudentDTO();
        student.setName(reader.getValue());

        reader.moveUp();
        reader.moveDown();
        student.setRollNo(Integer.parseInt(reader.getValue()));

        reader.moveUp();
        reader.moveDown();
        try 
        {
            student.setEnrollmentDate(new SimpleDateFormat("yyyy-MM-dd").parse(reader.getValue()));
        } 
        catch (ParseException e) 
        {
            e.printStackTrace();
        }

        reader.moveUp();
        reader.moveDown();
        try 
        {
            student.setSampleTimeStamp(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(reader.getValue()));
        }
        catch (ParseException e) 
        {
            e.printStackTrace();
        }

        reader.moveUp();
        reader.moveDown();
        student.setSalary(new BigDecimal(reader.getValue()));

        return student;
    }

}

reader.getAttribute(0) 的 StackTrace

java.lang.IllegalArgumentException
    at org.springframework.util.xml.XMLEventStreamReader.getAttribute(XMLEventStreamReader.java:211)
    at org.springframework.util.xml.XMLEventStreamReader.getAttributeValue(XMLEventStreamReader.java:192)
    at com.thoughtworks.xstream.io.xml.StaxReader.getAttribute(StaxReader.java:92)
    at com.thoughtworks.xstream.io.ReaderWrapper.getAttribute(ReaderWrapper.java:56)
    at com.example.demo.utility.StudentConverter.unmarshal(StudentConverter.java:33)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
    at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1230)
    at org.springframework.oxm.xstream.XStreamMarshaller.doUnmarshal(XStreamMarshaller.java:826)
    at org.springframework.oxm.xstream.XStreamMarshaller.unmarshalXmlStreamReader(XStreamMarshaller.java:786)
    at org.springframework.oxm.xstream.XStreamMarshaller.unmarshalXmlEventReader(XStreamMarshaller.java:777)
    at org.springframework.oxm.support.AbstractMarshaller.unmarshalStaxSource(AbstractMarshaller.java:411)
    at org.springframework.oxm.support.AbstractMarshaller.unmarshal(AbstractMarshaller.java:354)
    at org.springframework.batch.item.xml.StaxEventItemReader.doRead(StaxEventItemReader.java:255)
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:92)
    at org.springframework.batch.item.support.SynchronizedItemStreamReader.read(SynchronizedItemStreamReader.java:55)
    at org.springframework.batch.item.support.SynchronizedItemStreamReader$$FastClassBySpringCGLIB$$987ea09.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at org.springframework.batch.item.support.SynchronizedItemStreamReader$$EnhancerBySpringCGLIB$$66d53b5e.read(<generated>)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:94)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:161)
    at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:119)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:113)
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273)
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82)
    at org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

[注意]:我尝试使用以下属性进行调试:

reader.getAttribute(0) -- 抛出错误

reader.getAttribute("name") -- 返回 null

reader.getAttributeCount() -- 总是返回 0

我不确定为什么 reader.getAttributeCount() 返回零,因为每个学生条目有 5 个字段。

我想要的只是对 StudentConverter.unmarshal 部分进行更多控制,我想通过它们的名称或某些标识符来获取属性值,而不是通过它们在 xml 中的位置,因为位置是动态的,以后可能会改变。

【问题讨论】:

    标签: java spring-boot spring-batch xstream


    【解决方案1】:

    当你有类似&lt;a b="..."&gt;...&lt;/a&gt; 的东西时,从 XML 的角度来看,a 是一个元素,b 是一个属性。

    您的 XML 没有任何属性。这就是为什么 .getAttributeCount() 为 0 而.getAttribute(0) 为例外。

    实现你想要的一个通常的方法是使用像Jackson这样的工具,并使用相关的配置/注释来根据需要输入和输出来匹配每个字段。有关如何处理它的基本说明,请参阅here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      相关资源
      最近更新 更多