- ベストアンサー
不特定ノードに出現する同じタグ要素の中身を置換して保存したい
- 特定のタグ要素がXML内のどこに現われるかわからない場合、その要素の中身を置換して元のXMLと同じ構造を保ったまま保存する方法を教えてください。
- XPathを使用して//hogeと指定すればnodeListが抽出できますが、それらのノードの絶対パスを知る方法があれば教えてください。
- DOMとXSLTの基礎を学んだことがあり、SAXには詳しくありません。だれでも良いので、どのような方法でも実現できる方法を教えていただけませんか?
- みんなの回答 (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が書き出されます。
その他の回答 (3)
- kazf
- ベストアンサー率100% (1/1)
変換前文字列と変換後文字列の対応がどこでされているのか不明なので 正しい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文書構造を保ったまま保存したいのです。
- MetalKing
- ベストアンサー率57% (15/26)
例題のものなら これでいいはずです 全ての要素にマッチするテンプレート <xsl:template match="*"> <xsl:element name="{name()}"> <xsl:apply-templates /> </xsl:element> </xsl:template>
- MetalKing
- ベストアンサー率57% (15/26)
XSLTなら 全ての要素にマッチするテンプレートを定義して、マッチした要素(即ち全て)をそのまま出力するようにします。 次に<hoge>にマッチするテンプレートを定義して、文字列を変換するようにします。
補足
「全ての要素にマッチするテンプレート」で既に<hoge>がマッチしてしまってうまくいかないのですが、よろしければサンプルコードなど書いていただけないでしょうか。 また<hoge>にマッチしても「同じ文字列」に置換したいわけではないのでXSLTではうまくいかないような気がするのですが。。。
お礼
実際にkazfさんのJavaコードをコンパイルして動作確認しました。test2.xmlが本当に「変換後文字列」になっていてむちゃくちゃ感動しました。 本当に本当にありがとうございました!