【Java】【XML】xPath ~XMLの参照・書き換え~

 ■ 用語

 XPath (XML Path Language)

 * XML から、条件に適合した部分の要素を取り出すための仕様
 => 詳細は、以下の関連記事を参照のこと

https://dk521123.hatenablog.com/entry/2015/06/06/100247
 ロケーションパス

 * ルートノードを起点としてノード指定方法

http://www.techscore.com/tech/XML/XPath/xpath02.html/
http://www.techscore.com/tech/XML/XPath/XPath3/xpath03.html/

 ■ サンプル

 SampleXml.java

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SampleXml {
   public static void main(String[] args) {
      try {
         // DOMパーサ用ファクトリの生成
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         // DOM Documentインスタンス用ファクトリの生成
         DocumentBuilder builder = factory.newDocumentBuilder();
         // 解析とDocumentインスタンスの取得
         File file = new File("conf/sample.xml");
         Document document = builder.parse(file);

         XPathFactory xPathFactory = XPathFactory.newInstance();
         XPath xpath = xPathFactory.newXPath();

         // 単一の要素を取得
         Node targetNode = (Node) xpath.evaluate(
               "main/logList/list[@code='e001' and @type='e']", document,
               XPathConstants.NODE);
         Node nodeForMessage = targetNode.getAttributes().getNamedItem("message");
         String result = nodeForMessage.getNodeValue();
         System.out.println("message : " + result);

         // 単一の要素を書き換える
         nodeForMessage.setNodeValue("Modified " + result);
         System.out.println("New message : " + nodeForMessage.getNodeValue());

         // 複数の要素を取得/書き換え
         NodeList targetNodeList = 
               (NodeList) xpath.evaluate("main/logList/list[@type='w']", document,
               XPathConstants.NODESET);
         for (int i = 0; i < targetNodeList.getLength(); i++) {
            Node nodeForMessage2 = targetNodeList.item(i).getAttributes().getNamedItem("message");
            String result2 = nodeForMessage2.getNodeValue();
            System.out.println("message : " + result2);
            nodeForMessage2.setNodeValue("Modified " + result2);
         }

         // 確認
         NodeList fixedNodeList = 
               (NodeList) xpath.evaluate("main/logList/list[@type='w']", document,
               XPathConstants.NODESET);
         for (int i = 0; i < fixedNodeList.getLength(); i++) {
            Node nodeForMessage2 = fixedNodeList.item(i).getAttributes().getNamedItem("message");
            String result2 = nodeForMessage2.getNodeValue();
            System.out.println("message : " + result2);
         }
         
         /*
          * DOMオブジェクトを文字列として出力
          */
         TransformerFactory transFactory = TransformerFactory.newInstance();
         Transformer transformer = transFactory.newTransformer();
         transformer.transform(new DOMSource(document), new StreamResult(file));
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
}

修正前

 conf/sample.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<main>
 <logList>
  <list code="w001" type="w" message="Worn 001"/>
  <list code="w002" type="w" message="Worn 002/>
  <list code="e001" type="e" message="Error 001"/>
  <list code="e002" type="e" message="Error 002"/>
  <day date="2014-07-01">
    <log time="10:00:00" type="w" code="w001"/>
    <log time="14:00:00" type="e" code="e001"/>
  </day>
  <day date="2014-07-02">
    <log time="13:00:00" type="e" code="e002"/>
    <log time="15:00:00" type="e" isUserError="true" code="e001"/>
  </day>
 </logList>
</main>

 出力結果

 Console
message : Error 001
New message : Modified Error 001
message : Worn 001
message : Worn 002
message : Modified Worn 001
message : Modified Worn 002

修正後

conf/sample.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?><main>
 <logList>
  <list code="w001" message="Modified Worn 001" type="w"/>
  <list code="w002" message="Modified Worn 002" type="w"/>
  <list code="e001" message="Modified Error 001" type="e"/>
  <list code="e002" message="Error 002" type="e"/>
  <day date="2014-07-01">
    <log code="w001" time="10:00:00" type="w"/>
    <log code="e001" time="14:00:00" type="e"/>
  </day>
  <day date="2014-07-02">
    <log code="e002" time="13:00:00" type="e"/>
    <log code="e001" isUserError="true" time="15:00:00" type="e"/>
  </day>
 </logList>
</main>

 参考文献

http://www6.airnet.ne.jp/manyo/xml/dom_java/step23.html
http://blog.goo.ne.jp/xmldtp/e/d7a9634935183c6a58745d4aedd8c775
http://msugai.fc2web.com/java/XML/XPath.html
 XPathによるノードの指定法
http://www.atmarkit.co.jp/fxml/rensai2/xmlmaster12/master12.html

関連記事

XML API の使い分けについて
https://dk521123.hatenablog.com/entry/2015/06/06/100247
xPathXMLの書き換え~
https://dk521123.hatenablog.com/entry/2014/06/17/011538