1

我有一个XML包含许多事件的大文件。我愿意unmarshal他们。因为它是一个大文件,我想unmarshal一个一个地给它们,所以整个文件不会存储在内存中。它适用于某些事件,但由于它无法映射到特定类,因为它已经在下一个事件中,因此对某些事件无效。

注意:我知道XMLEventReader但他们中的大多数人都提到它不是非常有效的内存,所以我正在尝试使用XMLStreamReader并完成它。

XML以下是包含事件的示例文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<extension>
    <extension>
        <c>
            <name>CName</name>
            <age>CAge</age>
        </c>
    </extension>
</extension>
<extension>
    <b>
        <name>BName</name>
        <age>BAge</age>
    </b>
</extension>
<a>
    <name>AName</name>
    <age>AAge</age>
</a>
<extension>
    <b>
        <name>BName</name>
        <age>BAge</age>
    </b>
</extension>

我有 3 个与它们相对应的类,它们将用于unmarshalling

@XmlRootElement(name = "a")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "a", propOrder = {"name","age"})
public class A
{
    private String name;
    private String age;
    //Getter, Setter and other constructors
}

@XmlRootElement(name = "extension")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "extension", propOrder = {"name","age"})
public class B
{
    @XmlPath("b/name/text()")
    private String name;
    @XmlPath("b/age/text()")
    private String age;
    //Getter, Setter and other constructors
}

@XmlRootElement(name = "extension")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "extension", propOrder = {"name","age"})
public class C
{
    @XmlPath("extension/c/name/text()")
    private String name;
    @XmlPath("extension/c/age/text()")
    private String age;
    //Getter, Setter and other constructors
}

以下是我的Main课程,将用于unmarshalling

public class Main{
     
    private Unmarshaller unmarshaller = null;
    private JAXBContext jaxbContext = null;
  
    public void unmarshaller(InputStream xmlStream) throws IOException, XMLStreamException, JAXBException {
        final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
        final XMLStreamReader streamReader = xmlInputFactory.createXMLStreamReader(xmlStream);
        
        //Navigate to next and start of the XML Elements
        streamReader.next();

        //Read Until the end of the file
        while (streamReader.hasNext()) {
            //Check if the element is "extension" if so its Class B or C
            if (streamReader.isStartElement() && streamReader.getLocalName().equalsIgnoreCase("extension")) {

                //Check if the next element also has "extension" if so its Class C
               //This is IMPORTANT step for mapping b/w Class B & C which is confusing me
                streamReader.next();

                if (streamReader.isStartElement() && streamReader.getLocalName().equalsIgnoreCase("extension")) {
                    //If there is 2 extension tag then its Class C
                    classSpecifier(C.class);
                    final C cInfo = unmarshaller.unmarshal(streamReader, C.class).getValue();
                    System.out.println(cInfo);
                }else{
                    //If there is no "extension" tag then its Class B
                    //THIS IS WHERE ITS FAILING: IF ITS NOT CLASS C THEN IT WOULD COME HERE BUT SINCE I HAVE 
                    //ALREADY MOVED TO NEXT ELEMENT TO CHECK IF ITS "extension" ITS UNABLE TO MAP THE WHOLE CLASS TO CLASS B
                    classSpecifier(B.class);
                    final B bInfo = unmarshaller.unmarshal(streamReader, B.class).getValue();
                    System.out.println(bInfo);
                }
            }else if(streamReader.isStartElement() && streamReader.getLocalName().equalsIgnoreCase("a")){
                //If there is no "extension" then its class A
                classSpecifier(A.class);
                final A aInfo = unmarshaller.unmarshal(streamReader, A.class).getValue();
                System.out.println(aInfo);
            }
        }
    }
    
    //Method to initialize the JAXBContext and Unmarshaller based on the incoming eventType
    private void classSpecifier(Class eventTypeClass) throws JAXBException {
        this.jaxbContext = JAXBContext.newInstance(eventTypeClass);
        unmarshaller = jaxbContext.createUnmarshaller();
    }
    
    public static void main(String args[]){
        try{
            InputStream xmlStream = Main.class.getClassLoader().getResourceAsStream("InputEPCISEvents.xml");
            unmarshaller(xmlStream);
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }
}

我面临的问题是 classBC.

  1. 我需要检查传入localName的是否是extension.
  2. 如果是,extension那么我需要检查下一个元素localName是否也是extension.
  3. 如果是,那么class C如果不是,那么class B
  4. 因为在Step-2我已经移动到streamreader.next()并且如果元素不是extension那么它无法将它映射到class B因为我已经移动到next()元素并且它没有整个类。

我正在寻找一些可以执行以下操作的解决方案:

  1. 如果第二次验证中的元素不是extension,则返回上一个元素,然后将整个类分配给class B.
  2. 在进行检查时分配streamReaderto ,以便您前进。但这也失败了。tempreadertempreader

有没有办法回到流中的前一个元素,否则我该如何解决这个问题?我希望我能够提供一个完整的解释。

4

0 回答 0