アプリ版:「スタンプのみでお礼する」機能のリリースについて

ある特定のタグ要素(例: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>

A 回答 (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が書き出されます。
    • good
    • 0
この回答へのお礼

実際にkazfさんのJavaコードをコンパイルして動作確認しました。test2.xmlが本当に「変換後文字列」になっていてむちゃくちゃ感動しました。
本当に本当にありがとうございました!

お礼日時:2005/02/02 03:05

変換前文字列と変換後文字列の対応がどこでされているのか不明なので


正しい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文書構造を保ったまま保存したいのです。

補足日時:2005/02/01 04:25
    • good
    • 0

例題のものなら これでいいはずです



全ての要素にマッチするテンプレート

<xsl:template match="*">
 <xsl:element name="{name()}">
  <xsl:apply-templates />
 </xsl:element>
</xsl:template>
    • good
    • 0

XSLTなら



全ての要素にマッチするテンプレートを定義して、マッチした要素(即ち全て)をそのまま出力するようにします。

次に<hoge>にマッチするテンプレートを定義して、文字列を変換するようにします。

この回答への補足

「全ての要素にマッチするテンプレート」で既に<hoge>がマッチしてしまってうまくいかないのですが、よろしければサンプルコードなど書いていただけないでしょうか。
また<hoge>にマッチしても「同じ文字列」に置換したいわけではないのでXSLTではうまくいかないような気がするのですが。。。

補足日時:2005/01/31 01:37
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!