1

大きな 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 のすべてのサブノードをチェックしてから、再び node: versionNumber="1.81" に移動し、そこで終了条件を満たします。 while ループ。

ノードの versionNumber のみを確認したいので、そのサブノードを反復する必要はなく、大きな xml ファイルの場合、バージョン 1.80 のすべてのサブノードを反復するには長い時間がかかります。ルート ノード (versionNumber) のみをチェックしたいのですが、最初のルート ノード (versionNumber=1.80) が一致しない場合、XMLStreamReader は次のルート ノード ((versionNumber=1.81)) に直接ジャンプする必要があります。しかし、xsr.nextTag() では達成できないようです。目的のルート ノードのみを反復処理する方法はありますか?

入力.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>
4

1 に答える 1

1

XPATHを使用してxmlからノードを取得できます

XML パス言語であるXPathは、XML ドキュメントからノードを選択するためのクエリ言語です。さらに、XPath を使用して、XML ドキュメントのコンテンツから値 (たとえば、文字列、数値、またはブール値) を計算することもできます。 Xpath とは何ですか

あなたのXPath式は

/fileVersionListWrapper/VersionList[@versionNumber='1.81']

つまり、属性が1.81である VersionList のみを返したいということです。

Java コード

私はあなたが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 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);
于 2015-06-10T09:34:00.093 に答える