[英]Efficiently unmarshaling a part of a large xml file with JAXB and XMLStreamReader
我想解組一個大型XML文件的一部分。 已經存在解決方案,但是我想針對自己的實現進行改進。
請看下面的代碼:( source )
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("VersionList")&&xsr.getElementText().equals("1.81")) {
xsr.nextTag();
}
我想為以下節點解編input.xml(如下所示):versionNumber =“ 1.81”
使用當前代碼,XMLStreamReader將首先檢查節點versionNumber =“ 1.80”,然后將檢查versionNumber的所有子節點,然后將其再次移至節點:versionNumber =“ 1.81”,在該節點處滿足以下條件: while循環。
因為我只想檢查node versionNumber,所以不需要迭代其子節點,並且對於大型xml文件,迭代1.80版的所有子節點將花費很長時間。 我只想檢查根節點(versionNumber),如果第一個根節點(versionNumber = 1.80)不匹配,則XMLStreamReader應該直接跳到下一個根節點((versionNumber = 1.81))。 但是使用xsr.nextTag()似乎無法實現。 有什么辦法只能迭代所需的根節點嗎?
input.xml中:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<fileVersionListWrapper FileName="src.h">
<VersionList versionNumber="1.80">
<Reviewed>
<commentId>v1.80(c5)</commentId>
<author>Robin</author>
<lines>47</lines>
<lines>48</lines>
<lines>49</lines>
</Reviewed>
<Reviewed>
<commentId>v1.80(c6)</commentId>
<author>Sujan</author>
<lines>82</lines>
<lines>83</lines>
<lines>84</lines>
<lines>85</lines>
</Reviewed>
</VersionList>
<VersionList versionNumber="1.81">
<Reviewed>
<commentId>v1.81(c4)</commentId>
<author>Robin</author>
<lines>47</lines>
<lines>48</lines>
<lines>49</lines>
</Reviewed>
<Reviewed>
<commentId>v1.81(c5)</commentId>
<author>Sujan</author>
<lines>82</lines>
<lines>83</lines>
<lines>84</lines>
<lines>85</lines>
</Reviewed>
</VersionList>
</fileVersionListWrapper>
您可以使用XPATH從xml獲取節點
XPath (XML路徑語言)是一種查詢語言,用於從XML文檔中選擇節點。 另外,XPath可用於根據XML文檔的內容計算值(例如,字符串,數字或布爾值)。 什么是Xpath 。
您的XPath表達式將是
/fileVersionListWrapper/VersionList[@versionNumber='1.81']
意味着您只想返回Version1.8屬性為1.81的版本
我已經假設您將xml作為字符串,因此您需要以下思路
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(xml));
Document document = builder.parse(inputSource);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/fileVersionListWrapper/VersionList[@versionNumber='1.81']");
NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
現在將簡單地遍歷每個節點
for (int i = 0; i < nl.getLength(); i++)
{
System.out.println(nl.item(i).getNodeName());
}
為了使節點回到xml,您將必須創建一個新Document並將節點附加到它。
Document newXmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = newXmlDocument.createElement("fileVersionListWrapper");
for (int i = 0; i < nl.getLength(); i++)
{
Node node = nl.item(i);
Node copyNode = newXmlDocument.importNode(node, true);
root.appendChild(copyNode);
}
newXmlDocument.appendChild(root);
獲得新文檔后,您將運行序列化程序以獲取xml。
DOMImplementationLS domImplementationLS = (DOMImplementationLS) document.getImplementation();
LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
String string = lsSerializer.writeToString(document);
現在您有了String xml,我假設您已經有一個Jaxb對象,它看起來類似於
@XmlRootElement(name = "fileVersionListWrapper")
public class FileVersionListWrapper
{
private ArrayList<VersionList> versionListArrayList = new ArrayList<VersionList>();
public ArrayList<VersionList> getVersionListArrayList()
{
return versionListArrayList;
}
@XmlElement(name = "VersionList")
public void setVersionListArrayList(ArrayList<VersionList> versionListArrayList)
{
this.versionListArrayList = versionListArrayList;
}
}
您將簡單地使用Jaxb解組器為您創建對象
JAXBContext jaxbContext = JAXBContext.newInstance(FileVersionListWrapper .class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(xmlString);
FileVersionListWrapper fileVersionListWrapper = (FileVersionListWrapper) jaxbUnmarshaller.unmarshal(reader);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.