プログラミング言語とネームスペース(2)

Javaのネームスペースの使い方の例です.JavaではネームスペースのハンドリングはNamespaceContextインタフェースをインプリメントしたクラスをXPathクラスに登録することで実現されます.

Interface NamespaceContext

実際のプログラムですが、従来のネームスペースなしとの違いは青色の部分です.ここでは、MusicLibraryNamespaceContextクラスがNamespaceContextインタフェースをインプリメントしています.

package XPathExample;

import java.io.IOException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import javax.xml.xpath.*;

public class XPathExample2 {

    public static void main(String[] args) 
        throws ParserConfigurationException, SAXException,
        IOException, XPathExpressionException{
        
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse("MusicLibraryNS.xml");
            
        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        MusicLibraryNamespaceContext mlnsc=new MusicLibraryNamespaceContext();
        xpath.setNamespaceContext(mlnsc);
        XPathExpression expr 
         = xpath.compile("/mlp:musicLibrary/cdp:cd[string(mlp:year) = '1994']/ttlp:title/text()");
        Object result = expr.evaluate(doc, XPathConstants.NODESET);
        NodeList nodes = (NodeList) result;
        for (int i = 0; i < nodes.getLength(); i++) {
            System.out.println("title=\""+nodes.item(i).getNodeValue()+"\""); 
        }
    }
}

MusicLibraryNamespaceContextはこのサンプル用に単純にネームスペースプリフィックスに対してネームスペースを返すだけのものを実装してあります.

package XPathExample;

import java.util.Iterator;
import javax.xml.*;
import javax.xml.namespace.NamespaceContext;

public class MusicLibraryNamespaceContext implements NamespaceContext{
    public String getNamespaceURI(String prefix) {
        if (prefix == null) throw new NullPointerException("Null prefix");
        else if ("mlp".equals(prefix)) return "uri:music:library";
        else if ("cdp".equals(prefix)) return "uri:music:cd";
        else if ("ttlp".equals(prefix)) return "uri:music:title";
        else if ("xml".equals(prefix)) return XMLConstants.XML_NS_URI;
        return XMLConstants.NULL_NS_URI;
    }
    public String getPrefix(String uri) {
        throw new UnsupportedOperationException();
    }
    public Iterator getPrefixes(String uri) {
        throw new UnsupportedOperationException();
    }
}

このプログラムで、結果は

title="The Dark Side of the Moon"

と出てくれます.Javaの場合NamespaceContextインタフェースをインプリメントしさえすればよいので拡張性は高いですが、簡単な実装が提供されていても良いような気もします.でもWEBを見ればインプリメントしたサンプルコードはあるので本当に使うときは参考にすればよいでしょう.例えばこの方のブログにあります.


しかしDOMはどうも扱いづらいです.XPathで"/mlp:musicLibrary/cdp:cd[string(mlp:year) = '1994']/ttlp:title/text()"とテキストノードまで選択してやらなければ、getNodeValue()でテキストを取り出せません.

やっかいなので、決めうちで

XPathExpression expr 
 = xpath.compile("string(/mlp:musicLibrary/cdp:cd[string(mlp:year) = '1994']/ttlp:title)");
Object result = expr.evaluate(doc, XPathConstants.STRING);
String title = (String) result;
System.out.println("title=\""+title+"\""); 

とやっても同じ結果になります.次は.netのVBを見たいと思います.