- PR -

XPathでのノードの取得

1
投稿者投稿内容
レオ
常連さん
会議室デビュー日: 2006/10/14
投稿数: 21
投稿日時: 2006-12-07 19:19
XPathを用いて、XMLからノードを取得しようとしております。

コード:
XPathFactory factory 
    = XPathFactory.newInstance();

XPath xpath = factory.newXPath();

XPathExpression expr 
    = xpath.compile(XPath式);

Object result = expr.evaluate(Node, XPathConstants.NODESET);

NodeList nodeList = (NodeList) result;



とすれば、ノードリストを取得できることは分かったのですが、
XMLの要素にプレフィックスが付いてる場合のノード取得方法に
ついて質問させていただきます。

プレフィックスが付いてる場合、例えばXPath式を
/pre:NodeA/pre:NodeB/・・・
のように指定するものと思っておりますが、プレフィックスに依らない
ような形でXMLからノードを取得することはできますでしょうか?

XMLは別の処理によって作成されたもので、決まったプレフィックスが付加
されるかは分からないという状況です。
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-07 19:54
多分DOMに展開するときにsetNamespaceAware(true)をDocumentBuilderFactoryに設定してないのでは?
レオ
常連さん
会議室デビュー日: 2006/10/14
投稿数: 21
投稿日時: 2006-12-07 20:37
返答ありがとうございます。

言葉が足りていなかったのですが、上で言ってるXMLとは
別のところから渡されたノードを指しています。

そのノードに対してgetPrefix()を行ってもnullが返って
きています。
setNamespaceAware(true)を設定したDocumentBuilderFactory
で新たなDocumentを作成して、そこにimportNode(Node,boolean)
でインポートしてみる、ということも試みてみましたがダメなようです。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2006-12-07 21:16
引用:

プレフィックスが付いてる場合、例えばXPath式を
/pre:NodeA/pre:NodeB/・・・
のように指定するものと思っておりますが、プレフィックスに依らない
ような形でXMLからノードを取得することはできますでしょうか?



できます。XPath式の中のプレフィックスは、対象XML文書中のプレフィックスと関係ありません。XPath式中のQNameはコンパイル後は名前空間とローカル名の組として処理されます。で、プレフィックスから名前空間へのマップは XPath.setNamespaceContext() で指定します。
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-08 10:40
失礼しました.
名前空間を有効にしているんですね。
名前空間を無効にするとlocalnameだけで取れるようになります。
この場合名前空間を無効にしたDocumentにimportNodeしてもだめなようで、いったんXMLとして展開して読み込みなおす必要がありそうです。
ちょっと面倒だけど、
nodeに必要な名前空間宣言はあるとして、

private final String style_sheet =
"<xsl:stylesheet version=\"2.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
"<xsl:output method=\"xml\"/>" +
"</xsl:stylesheet>";
StringWriter sw = new StringWriter();
StringReader sr = new StringReader(style_sheet);
StreamSource xlt = new StreamSource(sr);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer tr = tf.newTransformer(xlt);
DOMSource source = new DOMSource(node);
StreamResult result = new StreamResult(sw);
tr.transform(source, result);
StringReader sr = new StringReader(sw.toString());
InputSource insrc = new InputSource(sr);
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
Document doc = df.newDocumentBuilder().parse(insrc);
Element node_new = doc.getDocumentElement();

でnode_newでやればできると思います。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-12-08 14:43
xsl:template match="*[local-name()= 'elementABC']"
名前空間on でも XPath式で できるはず。
そういう 設計 はダメと、よく言われている。
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-08 15:27
これはそのとおりですね。
XPathExpression expr = xpath.compile("*[local-name()='NodeA']/*[local-name()='NodeB'/..");
で取得するのが正しいと思います。


1

スキルアップ/キャリアアップ(JOB@IT)