Dom 4 j and XPS

10132 ワード

多くのものは長い間使わないで、少し疎遠になりました。ネットで資料を整理しました。この便利さをなくしてから探します。
先にコードを付けます:

<?xml version="1.0" encoding="GBK"?>
<resin xmlns="http://caucho.com/ns/resin" xmlns:resin="http://caucho.com/ns/resin/core">  
  <server> 
    <http server-id="" host="*" port="9088"/>  
  </server> 
</resin>


package com.abc;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 *   Resin.conf   
 */
public class ResinConfHelper {
    private static final String HTTP_SERVER_NODE = "//resin/server/http";
    private static final String DEFAULT_NS = "http://caucho.com/ns/resin";
    private static final String RESIN_NS = "http://caucho.com/ns/resin/core";
    private static final String DEFAULT_NS_KEY = "default";
    private static final String RESIN_NS_KEY = "resin";
    private static final String DEFAULT_ENCODING = "GBK";
    private String resinConfFilePath;
    private Document doc;
    public ResinConfHelper(String resinConfFilePath) {
        this.resinConfFilePath = resinConfFilePath;
    }
    
    public String getHttpPort() {
        return getAttributeValue(HTTP_SERVER_NODE, "port");
    }
    
    public void setHttpPort(String port) {
        setAttributeValue(HTTP_SERVER_NODE, "port", port);
    }
    
    public void setHttpPort(int port) {
        setAttributeValue(HTTP_SERVER_NODE, "port", String.valueOf(port));
    }

    public void init() throws DocumentException {
        Map<String, String> namespaceURIs = new HashMap<String, String>();
        namespaceURIs.put(DEFAULT_NS_KEY, DEFAULT_NS);
        namespaceURIs.put(RESIN_NS_KEY, RESIN_NS);

        DocumentFactory docFactory = new DocumentFactory();
        docFactory.setXPathNamespaceURIs(namespaceURIs);

        SAXReader reader = new SAXReader(docFactory);
        File resinConfFile = new File(resinConfFilePath);
        doc = reader.read(resinConfFile);
    }

    public void save() throws IOException {
        XMLWriter writer = null;
        try {
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding(DEFAULT_ENCODING); //   XML  
            writer = new XMLWriter(new FileWriter(resinConfFilePath), format);
            writer.write(doc);
        }
        catch (Exception e) {
            System.err.println(e);
        }
        finally {
            IoUtils.closeQuietly(writer);
        }
    }

    public String getTextValue(String xPath) {
        return getElementByXPath(xPath).getTextTrim();
    }

    public String getAttributeValue(String xPath, String attrName) {
        return getElementByXPath(xPath).attributeValue(attrName);
    }

    private Element setAttributeValue(String xPath, String attrName, String attrValue) {
        return getElementByXPath(xPath).addAttribute(attrName, attrValue);
    }
    
    private Element getElementByXPath(String xPath) {
        return (Element) doc.selectSingleNode(getXPathWithNSByDefualt(xPath));
    }
    
    private static String getXPathWithNSByDefualt(String xpath) {
        xpath = xpath.replaceAll("/(\\w)", "/" + "default:$1"); // replace start with "/"
        xpath = xpath.replaceAll("^(\\w)", "default:$1"); // replace start with word
        return xpath;
    }

    public static void main(String[] args) throws Exception {
        
        String file = "resin.conf";
        ResinConfHelper helper = new ResinConfHelper(file);
        helper.init();
        System.out.println(helper.getHttpPort());
        
        helper.setHttpPort(9088);
        helper.save();
    }

}

---------------------------------
ポイント:
XMLが名前空間を持っている場合は、直接に元に馴染みのあるXXath文法で対応するノードが得られない。
XMLを解析する前に、該当する名前空間を設定し、XPSに対応する処理を取得ノードの前に行う必要があります。
---------------------------------
xpath文法
1、選択ノード
XPTathは経路表現を用いてXMLドキュメントでノードを選択し、ノードは経路またはステップに沿って選択される。
共通のパス表現:
表式
説明
nodename
現在のノードのすべてのサブノードを選択
を選択します。
ルートノードから選択
//
選択された現在のノードにマッチしてドキュメント内のノードを選択します。位置を考慮しないでください。
..。
現在のノードを選択
..。
現在のノードの親ノードを選択
@
属性を選択
実例
パス表現
結果
book store
book store要素のすべてのサブノードを選択します。
/book store
ルート要素ブックを選択
book store/book
book storeの下の名前がbookのすべてのサブ要素を選択します。
//book
すべてのbookのサブ要素をドキュメント内の位置に関係なく選択します。
book store/book
book storeの下の名前がbookという子孫のすべての要素を選択して、それらがbook storeの下のどの位置にあるかに関わらず。
//@lang
langという名前の属性をすべて選択します。
2、述語(Predicates)
述語は特定のノードを検索するために用いられ、または特定の値を含むノード。
述語は四角い括弧にはめ込まれている。
実例
一般的な述語のいくつかのパス表現:
パス表現
結果
/book store/book[1]
book storeに属する最初のbook要素を選択します。
/book store/book[last()
book storeに属する最後のbook要素を選択します。
/book store/book[last()-1]
book storeに属する最後から二番目のbook要素を選択します。
/book store/book[position()<3]
一番前の二つはbook store要素のサブ要素に属するbook要素です。
//title[@lang]
langという属性を持つすべてのtitle要素を選択します。
//title[@lang='eng']
すべてのtitle要素を選択して、これらの要素がengのlang属性を持つことを要求します。
/book store/book[price]35.00]
すべてのbook store要素のbook要素を選択して、book要素のサブ元素price元素の値が35.00より大きいことを要求します。
/book store/book[price]35.00/title
すべてのbook store要素の中のbook要素のtitle元素を選択して、book元素のサブ元素price元素の値が35.00より大きいことを要求します。
3、不明なノードを選択する
XPTathワイルドカードは未知のXML要素を選択するために使用できます。
ワイルドカード
説明

任意の要素ノードにマッチ
@*
任意の属性ノードにマッチ
node()
任意のタイプのノードにマッチします。
実例
パス表現
結果
/book store/*
book store要素のすべてのサブノードを選択します。
//*
ドキュメント内のすべての要素を選択します。
//title[@*]
属性を持つすべてのtitle要素を選択します。
4、いくつかのパスを選択する
パス表現に「*」演算子を使うことで、いくつかのパスを選択できます。
実例(「|」を「|」に置き換える)
パス表現
結果
//book/title|book/price
すべてのbook要素のtitleとprice元素を選択します。
//title//price
すべてのドキュメントのtitleとprice要素を選択します。
//book store/book/title|price
すべてのbook store要素に属するbook要素のtitle要素と、ドキュメント内のすべてのprice要素を選択します。
5、XPS軸
軸は、現在のノードに対するノードセットを定義することができます。
軸の名前
結果
アンサー
現在のノードのすべての先輩(父、祖父など)を選択します。
ancestor-or-self
現在のノードのすべての先輩(父、祖父など)と現在のノード自体を選択します。
atribute
現在のノードのすべての属性を選択します。
ちどり
現在のノードのすべてのサブ要素を選択します。
descendant
現在のノードのすべての子孫要素(子、孫など)を選択します。
descendant-or-self
現在のノードのすべての子孫要素(子、孫など)と現在のノード自体を選択します。
フォローウイング
ドキュメント内の現在のノードの終了ラベルの後にあるすべてのノードを選択します。
namespace
現在のノードのすべての名前空間ノードを選択します。
parent
現在のノードの親ノードを選択します。
preceding
ドキュメント内の現在のノードの開始ラベル前のすべてのノードを選択します。
preceding-sibling
現在のノードの前のすべての同級ノードを選択します。
self
現在のノードを選択します。
6、パス
Ø  位置パス式
位置経路は絶対であっても良いし、相対的であっても良い。
絶対パスは正のスラッシュから始まりますが、相対パスはそうではありません。2つの場合、位置経路はいずれも1つまたは複数のステップを含み、各ステップはスラッシュで分割される。
Ø  絶対位置パス:/Step/Step/…
Ø  相対位置パス:Step/Step/…
各ステップは、現在のノードセットの中のノードに基づいて計算される。
Ø  ステップ(ステップ)は、以下を含む。
軸(axis):選択されたノードと現在のノードとの間のツリー関係を定義します。
ノードテスト(node-test):ある軸の内部のノードを識別する
ゼロまたは複数の述語(predicate):選択されたノードセットをより深く抽出する。
ステップの文法:軸名称:ノードテスト[述語]
実例
実例

結果
child::book
現在のノードに属するすべてのサブ要素のbookノードを選択します。
atribute:lang
現在のノードのlang属性を選択します。
child:*
現在のノードのすべてのサブ要素を選択します。
atribute:*
現在のノードのすべての属性を選択します。
child::text()
現在のノードのすべてのテキストサブノードを選択します。
child::node()
現在のノードのすべてのサブノードを選択
descendant:book
現在のノードのすべてのbookの子孫を選択します。
ancestor:book
現在のノードのすべてのbook先輩を選択します。
ancestor-or-self:book
現在のノードのすべてのbook先輩および現在のノードを選択する(偽のノードがbookノードの場合)
child:*/child:price
現在のノードのすべてのprice孫を選択します。
7、XPS演算子
演算子
説明
実例
戻り値

二つのノードセットを計算します。
//book//cd
bookとckの要素があるすべてのノードセットを返します。

足し算
6+4
10
を選択します。
減算
6-4
2

掛け算
6*4
24。
div
法を割る
8 div 4
2
を選択します。
等しい
price=9.80
priceが9.80なら、trueに戻ります。priceが9.90ならfasleに戻ります。
!=
等しくない
price9.80
priceが9.90なら、trueに戻ります。priceが9.80ならfasleに戻ります。
<>
以下
price<9.80
priceが9.00なら、trueに戻ります。priceが9.90ならfasleに戻ります。
<=
小なりイコール
price==9.80
priceが9.00なら、trueに戻ります。priceが9.90ならfasleに戻ります。
>
大きい
price>9.80
priceが9.90なら、trueに戻ります。priceが9.80ならfasleに戻ります。
>=
大きいか等しい
price>=9.80
priceが9.90なら、trueに戻ります。priceが9.70ならfasleに戻ります。
or
または
price=9.80 or price=9.70
priceが9.80なら、trueに戻ります。priceが9.50ならfasleに戻ります。
and
を選択します
price>9.00 and price<9.90>
priceが9.80なら、trueに戻ります。priceが8.50ならfasleに戻ります。
mod
除算の余りを計算する
5 mod 2
1
参考:
http://blog.csdn.net/chifengxin/article/details/7035885
http://www.blogjava.net/eclipser/articles/228367.html
http://blog.csdn.net/blueman2012/article/details/6684177
http://selvemen.iteye.com/blog/1139990