1. ホーム
  2. java

[解決済み] 複数の子ノードを持つxmlファイルの読み込み

2022-02-19 02:15:24

質問

以下のようなXMLファイルがあるとします。

<top>
    <CRAWL>
        <NAME>div[class=name],attr=0</NAME>
        <PRICE>span[class~=(?i)(price-new|price-old)],attr=0</PRICE>
        <DESC>div[class~=(?i)(sttl dyn|bin)],attr=0</DESC>
        <PROD_IMG>div[class=image]>a>img,attr=src</PROD_IMG>
        <URL>div[class=name]>a,attr=href</URL>
    </CRAWL>
    <CRAWL>
        <NAME>img[class=img],attr=alt</NAME>
        <PRICE>div[class=g-b],attr=0</PRICE>
        <DESC>div[class~=(?i)(sttl dyn|bin)],attr=0</DESC>
        <PROD_IMG>img[itemprop=image],attr=src</PROD_IMG>
        <URL>a[class=img],attr=href</URL>
    </CRAWL>
</top>

タグの中に入ってくる値を使って、他の関数をしています。それぞれ別の値を持っていて、その値を別の操作に使っています。

よろしくお願いします

解決方法は?

私の理解が正しければ、XMLフラグメント内に存在するすべてのタグからデータを抽出しようとしているのですね。これには複数の解決策があります。以下にそれらを列挙します。

  1. XPath。XMLの構造が正確に分かっている場合、各ノード=CRAWLに対してXPathを採用することで、タグ内のデータを検索することができます。

    // Instantiate XPath variable
    XPath xpath = XPathFactory.newInstance().newXPath();
    // Define the exact XPath expressions you want to get data for:
    XPathExpression name     = xpath.compile("//top/CRAWL/NAME/text()");
    XPathExpression price    = xpath.compile("//top/CRAWL/PRICE/text()");
    XPathExpression desc     = xpath.compile("//top/CRAWL/DESC/text()");
    XPathExpression prod_img = xpath.compile("//top/CRAWL/PROD_IMG/text()");
    XPathExpression url      = xpath.compile("//top/CRAWL/URL/text()");
    
    

この時点で、上記の各変数は、各タグのデータが入っていることになります。これをそれぞれの配列に落とし込むと、すべての要素に各タグのデータが入ることになります。

  1. もう1つの(より効率的な)解決策は、DOMベースのパージングを行うことでデータを保存させることです。

    // Instantiate the doc builder
    DocumentBuilder xmlDocBuilder = domFactory.newDocumentBuilder();
    Document xmlDoc               = xmlDocBuilder.parse("xmlFile.xml");
    // Create NodeList of element tag "CRAWL"
    NodeList crawlNodeList = xmlDoc.getElementsByTagName("CRAWL");
    // Now iterate through each item in the NodeList and get the values of 
    // each of the elements in Name, Price, Desc etc.
    for (Node node: crawlNodeList) {
         NamedNodeMap subNodeMap = node.getChildNodes();
         int currentNodeMapLength = subNodeMap.getLength();
    
         // Get each node's name and value
         for (i=0; i<currentNodeMapLength; i++){
              // Iterate through all of the values in the nodeList, 
              // e.g. NAME, PRICE, DESC, etc.
              // Do something with these values
         }
    }
    
    

お役に立てれば幸いです。