ある特定のタグ要素(例:hoge)がXML内のどこに現われるかわからないとき、それらの要素の中身を置換して、元のXMLと同じ構造を保ったまま保存したいと考えています。
XPathを使って//hogeと指定すればnodeListが抽出できますが、それらのrootNodeからの絶対パスを知る方法があればよいのですが。。。
当方DOMとXSLTを多少かじった程度で、SAXについては全くわかりませんが、どんな方法でもよいので実現できる方法があったらどなたかご教授くださいませ。
<?xml version="1.0" encoding="Shift_JIS"?>
<root>
<hoge>変換前文字列1</hoge>
<aaa>
<hoge>変換前文字列2</hoge>
</aaa>
<bbb>
<ccc>
<hoge>変換前文字列3</hoge>
</ccc>
<hoge>変換前文字列4</hoge>
<hoge>変換前文字列5</hoge>
</bbb>
</root>
上記のようなXMLを下記のように変更したい。
<?xml version="1.0" encoding="Shift_JIS"?>
<root>
<hoge>変換後文字列1</hoge>
<aaa>
<hoge>変換後文字列2</hoge>
</aaa>
<bbb>
<ccc>
<hoge>変換後文字列3</hoge>
</ccc>
<hoge>変換後文字列4</hoge>
<hoge>変換後文字列5</hoge>
</bbb>
</root>
No.4ベストアンサー
- 回答日時:
TextクラスはNodeクラスを継承しているのでsetNodeValue()/getNodeValue()を利用できます。
Textクラス特有のメソッドsetData()/getData()でも動きは同じです。前回のコードでは、メモリ上のDocumentは、すでに文字列変換されています。
ただ、これをファイルに書き出す(保存する)場合は、もう一つ手順が必要です。
File file = new File("test2.xml");
Transformer t = TransformerFactory.newInstance().newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(file);
t.transform(source, result);
このコードを実行すると、ファイル"test2.xml"に変換後のXMLが書き出されます。
実際にkazfさんのJavaコードをコンパイルして動作確認しました。test2.xmlが本当に「変換後文字列」になっていてむちゃくちゃ感動しました。
本当に本当にありがとうございました!
No.3
- 回答日時:
変換前文字列と変換後文字列の対応がどこでされているのか不明なので
正しいXSLTは書けないかもしれませんが、<hoge>変換前文字列</hoge>を<hoge>変換後文字列</hoge>
に変換するXSLTはこんな感じになります。
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match=*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="hoge">
<xsl:copy>変換後文字列</xsl:copy>
</xsl:template>
</xsl:stylesheet>
もし、文字列の変換ルールが別ファイルや配列などで定義されているのであれば、
XSLTでは難しいです。JavaでDOMまたはSAXを扱って変換する方がいいでしょう。
Javaでやるなら、こんな感じです。
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
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 org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
-- (略) --
Map mapping = new HashMap();
mapping.put("変換前文字列1", "変換後文字列1");
mapping.put("変換前文字列2", "変換後文字列2");
mapping.put("変換前文字列3", "変換後文字列3");
mapping.put("変換前文字列4", "変換後文字列4");
mapping.put("変換前文字列5", "変換後文字列5");
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document document = null;
InputStream is = null;
try {
is = getClass().getResourceAsStream("test.xml");
document = builder.parse(is);
} finally {
if (is != null) {
is.close();
}
}
if (document != null) {
NodeList hoges = XPathAPI.selectNodeList(document, "//hoge/text()");
for (int i = 0, length = hoges.getLength(); i < length; i++) {
Text hogeText = (Text) hoges.item(i);
hogeText.setNodeValue((String) mapping.get(hogeText
.getNodeValue()));
}
}
この回答への補足
kazfさん、非常に参考になりました。ありがとうございます。書いてくださったXSLTについては目から鱗でした。
Javaについては全くの素人なので書いてくださったJavaコードについて少し教えてください。
Text hogeText = (Text) hoges.item(i);
hogeTextというのはNodeではなくTextなんですよね。それに対して.setNodeValue();というのはできるのでしょうか。
また無事NodeList hogesには文字列変換後のNodeListが格納されたとして、それを元のdocumentにどう反映させたらよいのでしょうか。それとももうこの時点でdocumentに反映されているのでしょうか。最終的に大元のXML文書構造を保ったまま保存したいのです。
No.2
- 回答日時:
例題のものなら これでいいはずです
全ての要素にマッチするテンプレート
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
No.1
- 回答日時:
XSLTなら
全ての要素にマッチするテンプレートを定義して、マッチした要素(即ち全て)をそのまま出力するようにします。
次に<hoge>にマッチするテンプレートを定義して、文字列を変換するようにします。
この回答への補足
「全ての要素にマッチするテンプレート」で既に<hoge>がマッチしてしまってうまくいかないのですが、よろしければサンプルコードなど書いていただけないでしょうか。
また<hoge>にマッチしても「同じ文字列」に置換したいわけではないのでXSLTではうまくいかないような気がするのですが。。。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Windows 10 バッチファイルの記述法とルールについてアドバイスをお願いいたします。 1 2022/04/13 10:50
- XML XML同じ名前の要素を自動で集約するツール 1 2022/04/11 09:21
- JavaScript javascriptで文字分割は、 split() などメソッド不要??? 4 2023/02/06 22:50
- JavaScript JavaScriptで「〇以上▲まで」の書き方 1 2022/07/20 14:44
- HTML・CSS 全部のアクセスを指定したページに転送させたい 2 2022/06/28 16:33
- C言語・C++・C# プログラミングのペーパーテスト 実行結果を表示せよ #include <stdio.h> int h 1 2022/07/09 15:27
- JavaScript javascriptで文字挿入でtoggleみたいなのはありますか? 2 2023/02/14 21:53
- PostgreSQL 【PostgreSQL】行の値の並びを変えるには 1 2023/03/21 16:46
- C言語・C++・C# プログラミングのペーパーテスト 実行結果がどのように表示されるか答えよ #include <stdi 1 2022/07/09 14:27
- Visual Basic(VBA) VBAでの共有パスにつきまして 1 2023/03/04 17:24
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
XML、XSLTの適応エラー(IEから...
-
CPUの考え方を教えてください ...
-
あるノードリストに、特定の名...
-
XMLで要素が記述された順番に意...
-
u_shortなどの省略した宣言につ...
-
バッチファイルでテキストファ...
-
ルート要素ノードが2個ある場合?
-
VB6.0ツリービューについて
-
東芝のDynabookなのですがアン...
-
双方向リストの関数
-
ノードとは
-
昔Winnyってありましたけど、あ...
-
UTF-8でエンコーディングとはど...
-
XML同じ名前の要素を自動で集約...
-
エクセルVBA ウェブ上のボタ...
-
同じタグ名の項目取得
-
oo4o OpenDatabaseの定数について
-
Web サイトにあるxmlファイルを...
-
VBでXMLファイルを作ると xmlns...
-
XML::LibXMLのfindnodes()で、...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
XML、XSLTの適応エラー(IEから...
-
xmlファイルが上手にHTMLに変換...
-
xmlstarletで他ファイルからエ...
-
不特定ノードに出現する同じタ...
-
xsltを利用して変換後改行が入る
-
XMLを出力する時のエラー原因
-
XSLTによるノードの抽出の際に...
-
XML+XSLTでの表示について
-
xalan でエラーが出るんですが。
-
XMLをxalanでXSL-FOに変換する
-
XSLTでの複数のXML検索結果を統...
-
XSLTでの正規表現判定
-
東芝のDynabookなのですがアン...
-
CPUの考え方を教えてください ...
-
バッチファイルでテキストファ...
-
XMLで要素が記述された順番に意...
-
XML同じ名前の要素を自動で集約...
-
UTF-8でエンコーディングとはど...
-
excelにてweb関数を使い、webデ...
-
XPathで途中に名前空間が設定さ...
おすすめ情報