12262


XMLのTEXTを更新したいのですが、DOMが全く変化しません。

[code]

    /**
     * xmlDocPtr &node     元のDOM
     * string text         挿入するTEXT
     * xmlChar *xpath_expr 更新する対象
     **/
    void DomParser::textUpdate(xmlDocPtr &node, string text, xmlChar *xpath_expr) {
    
        // XpathでDOMを抽出する。(動作確認済み)
        xmlNodeSetPtr dom = scrapeNodeList(node, xpath_expr);
    
        if (!xmlXPathNodeSetIsEmpty(dom)) {
            for (int i = 0; i < dom->nodeNr; i++) {
                // 既存TEXTの除去
                xmlNodePtr node = xmlXPathNodeSetItem(dom, i);
                xmlUnlinkNode(node->children);
                xmlFree(node->children);
    
                // 新規TEXTの追加
                xmlNodePtr new_text = xmlNewText((xmlChar*)text.c_str());
                xmlAddChild(node, new_text);
            }
        }
    }
    
[/code]

何がいけないのでしょうか？

> argus さん

ご回答ありがとうございました。  
検証コードを拝見しました。  
私の実装と目立ったロジックの差異がないため、もしやと思い、  
こちらのソースでも、  
更新後のcontent内容出力してみました。

結果は更新されていました。しかし、何度確認しても、更新後viでxmlを開くと、  
更新されていない状態で表示されます。

ドキュメントに対してコミットのようなことをする必要があるのでしょうか？


CC BY-SA 3.0
2015-07-10T10:40:38.227
12254
2015-07-15T03:44:12.523
2015-07-15T02:45:36.073
8396
8396
question
c++ xpath dom
C++でのlibxml2とXpathを使用したxml解析


検証用のコードを書いてみました。環境は以下の通りです。

[code]

    OS: Ubuntu Linux 15.04
    C++ compiler: GNU C++ 4.9.2
    libxml2: 2.9.2
    
[/code]

**replace_xml_test.cc**

[code]

    #include <iostream>
    #include <string.h>
    #include <libxml/xmlreader.h>
    #include <libxml/xpath.h>
    
    using namespace std;
    
    void textUpdate(xmlDocPtr &node, string text, xmlChar *xpath_expr) {
    
      xmlXPathContextPtr ctx = xmlXPathNewContext(node);
      xmlXPathObjectPtr xmlobj = xmlXPathEvalExpression(xpath_expr, ctx);
      xmlNodeSetPtr dom = xmlobj->nodesetval;
    
      if (!xmlXPathNodeSetIsEmpty(dom)) {
        for (int i = 0; i < dom->nodeNr; i++) {
          xmlNodePtr node = xmlXPathNodeSetItem(dom, i);
          xmlUnlinkNode(node->children);
          xmlFree(node->children);
    
          xmlNodePtr new_text = xmlNewText((xmlChar*)text.c_str());
          xmlAddChild(node, new_text);
        }
      }
    }
    
    int main(int argc, char** argv) {
      char *file = argv[1];
      char *text = argv[2];
      char *xpath_expr = argv[3];
    
      xmlDocPtr nodes = xmlParseFile(file);
      textUpdate(nodes, string(text), (xmlChar *)xpath_expr);
    
      xmlXPathContextPtr ctx = xmlXPathNewContext(nodes);
      xmlXPathObjectPtr xmlobj = xmlXPathEvalExpression((xmlChar *)xpath_expr, ctx);
      xmlNodeSetPtr dom = xmlobj->nodesetval;
      for(int i=0;i<dom->nodeNr; i++){
        xmlNodePtr node = xmlXPathNodeSetItem(dom, i);
        cout << node->children->content << endl;
      }
    
      // 変更内容を XML ファイルに反映させる場合は以下を実行
      // xmlSaveFileEnc(file, nodes, "UTF-8");
    
      return 0;
    }
    
[/code]

エラーチェックや終了処理は省いてあります。コードのコンパイルは以下の様にして行いました。

[code]

    $ g++ -I/usr/include/libxml2 -O replace_xml_text.cc -lxml2 -o replace_xml_text
    
[/code]

以下は入力用の XML ファイルです。

**input.xml**

[code]

    <?xml version="1.0" encoding="us-ascii" ?>
    <foo>
      <bar>hoge</bar>
      <bar>fuga</bar>
      <bar>piyo</bar>
    </foo>
    
[/code]

実行します。

[code]

    $ ./replace_xml_text input.xml 'Hi, World!' '//*/*'
    Hi, World!
    Hi, World!
    Hi, World!
    
[/code]

`xmlSaveFileEnc()` を実行した場合の `input.xml`(内容が更新されています)。

[code]

    $ cat input.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <foo>
      <bar>Hi, World!</bar>
      <bar>Hi, World!</bar>
      <bar>Hi, World!</bar>
    </foo>
    
[/code]


CC BY-SA 3.0
2015-07-10T13:50:19.363
12262
2015-07-15T03:44:12.523
2015-07-15T03:44:12.523
12254
answer