1. 程式人生 > >在xml裡增加節點時添加回車(libxml2)

在xml裡增加節點時添加回車(libxml2)


上一個關於libxml2的一篇文章中F. 新增屬性例程程式碼 ,新增的keyword結點後面沒有回車,
跟後面的結點擠在一行了,不是很好看。
例如,有以下的xml例子檔案
 1<?xml version="1.0"?>
 2<BODY>
 3  <filesystem>
 4    <filesystemKeyData>
 5      <filesystemName>Ext3</filesystemName>
 6      <versionNumber>123</versionNumber>
 7      <
option>good</option>
 8    </filesystemKeyData>
 9    <timestampSec>456</timestampSec>
10    <status>heasjdkfjaskdfjsk</status>
11  </filesystem>
12  <filesystem>
13    <filesystemKeyData>
14      <filesystemName>Ext3</filesystemName>
15      <
versionNumber>123</versionNumber>
16      <option>good</option>
17    </filesystemKeyData>
18    <timestampSec>456</timestampSec>
19    <status>heasjdkfjaskdfjsk</status>
20  </filesystem>
21</BODY>


例如,使用該文章例子中的程式碼在上面的filesystem節點的最後插入一個keyword的子結點後的,
該xml檔案的表示如下:

 1<?xml version="1.0"?>
 2<BODY>
 3  <filesystem>
 4    <filesystemKeyData>
 5      <filesystemName>Ext3</filesystemName>
 6      <versionNumber>123</versionNumber>
 7      <option>good</option>
 8    </filesystemKeyData>
 9    <timestampSec>456</timestampSec>
10   <status>heasjdkfjaskdfjsk</status>
11  <keyword1>hello</keyword1><keyword2>hello</keyword2><keyword3>hello</keyword3></filesystem>
12  <filesystem>
13    <filesystemKeyData>
14      <filesystemName>Ext3</filesystemName>
15      <versionNumber>123</versionNumber>
16      <option>good</option>
17    </filesystemKeyData>
18    <timestampSec>456</timestampSec>
19    <status>heasjdkfjaskdfjsk</status>
20    <keyword1>hello</keyword1><keyword2>hello</keyword2><keyword3>hello</keyword3></filesystem>
21</BODY>

你會發現keyword和/filesystem像下面那樣被擠在一起了,這並不是我們想要的.
<keyword1>hello</keyword1><keyword2>hello</keyword2><keyword3>hello</keyword3></filesystem>

通過設定 xmlKeepBlanksDefault(0) 以及 xmlSaveFormatFile(...)的format引數設定成1,都無法實現
在新追加的結點後面添加回車換行。
www.xmlsoft.org的官方網站的maillist裡關於這方面的資訊非常少。但是,對我幫助最大還是
http://mail.gnome.org/archives/xml/2007-May/msg00043.html 這個問題裡的例子程式碼,裡面在設定
屬性的時候用的xmlReadFile函式,而且options引數設定的是XML_PARSE_NOBLANKS。

於是,我們用xmlReadFile(...),把它的options引數設定成XML_PARSE_NOBLANKS後,就可以自動新增
回車了。

那,重新修正了的例子程式是如下那樣,裡面只修改了兩條語句。

 1#include <stdio.h>
 2#include <string.h>
 3#include <stdlib.h>
 4#include <libxml/xmlmemory.h>
 5#include <libxml/parser.h>
 6void
 7parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword)
 8{
 9   xmlNewTextChild (cur, NULL, "keyword1", keyword);
10  xmlNewTextChild (cur, NULL, "keyword2", keyword);
11  xmlNewTextChild (cur, NULL, "keyword3", keyword);
12  return;
13}

14
15xmlDocPtr
16parseDoc (char *docname, char *keyword)
17{
18  xmlDocPtr doc;
19  xmlNodePtr cur;
20  //doc = xmlParseFile (docname);21  doc = xmlReadFile(docname, NULL, XML_PARSE_NOBLANKS); 
//讀取xml檔案時忽略空格
22  if (doc == NULL)
23  {
24      fprintf (stderr, "Document not parsed successfully. \n");
25      return (NULL);
26  }

27  cur = xmlDocGetRootElement (doc);
28  if (cur == NULL)
29  {
30      fprintf (stderr, "empty document\n");
31      xmlFreeDoc (doc);
32      return (NULL);
33  }

34  if (xmlStrcmp (cur->name, (const xmlChar *) "BODY"))
35  {
36      fprintf (stderr, "document of the wrong type, root node != story\n");
37      xmlFreeDoc (doc);
38      return (NULL);
39  }

40  cur = cur->xmlChildrenNode;
41  while (cur != NULL)
42  {
43      if ((!xmlStrcmp (cur->name, (const xmlChar *) "filesystem")))
44      {
45         parseStory (doc, cur, keyword);
46      }

47      cur = cur->next;
48  }

49  return (doc);
50}

51
52int
53main (int argc, char **argv)
54{
55  char *docname;
56  char *keyword;
57  xmlDocPtr doc;
58  if (argc <= 2)
59  {
60      printf ("Usage: %s docname, keyword\n", argv[0]);
61      return (0);
62  }

63  docname = argv[1];
64  keyword = argv[2];
65  doc = parseDoc (docname, keyword);
66  if (doc != NULL)
67  {
68      //xmlSaveFormatFile (docname, doc, 0);69      xmlSaveFormatFile (docname, doc, 1);
70      xmlFreeDoc (doc);
71  }

72  return (1);
73}

74 修正1:是把xmlParseFile替換成xmlReadFile,並且是options引數設定成XML_PARSE_NOBLANKS;否則的話是不會在結點後面添加回車的。
修正2:把xmlSaveFormatFileformat引數修改成1,否則在使用xmlReadFile開啟的xml檔案時,在生成的xml檔案裡是會把所有的結點都放到一行裡顯示。
另外:xmlKeepBlanksDefault(0) 除了在讀入xml檔案時忽略空白之外,還會在寫出xml檔案時在每行前面放置縮排(indent)。如果使用xmlKeepBlanksDefault(1) 則你會發現每行前面的縮排就沒有了,但不會影響回車換行。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
額外話題: 更新結點的值得時候segement fault錯誤
下面的程式碼是更新XML檔案裡的某些結點元素的值的簡單的例子。
 1    xmlNodePtr element;
 2    //  3    xmlNodePtr childrenNodePtr = element->children;
 4    while(childrenNodePtr != NULL)
 5    {
 6        if(childrenNodePtr->type == XML_TEXT_NODE)
 7        {
 8            xmlNodeSetContent(childrenNodePtr, (const xmlChar*)"world");
 9            return NORMAL_RET;
10        }

11        childrenNodePtr = childrenNodePtr->next;
12    }

執行該段程式碼,有時候會在使用的API函式xmlNodeSetContent
處發生段錯誤,但不是100%發生。
只有該結點在原來值是某些字串的時候會發生該錯誤,比如說,
原來的值是"zo"的時候就會讓程式崩潰。
閱讀了libxml2的原始碼發現,xmlNodeSetContent函式,在把結點值
設定成新的字串之前會呼叫xmlFree(cur->content)來釋放掉原來
字串緩衝區的記憶體。
xmlNodeSetContent函式的程式碼片斷:

相關推薦

xml增加節點回車(libxml2)

上一個關於libxml2的一篇文章中F. 新增屬性例程程式碼 ,新增的keyword結點後面沒有回車,跟後面的結點擠在一行了,不是很好看。例如,有以下的xml例子檔案  1<?xml version="1.0"?> 2<BODY> 3  <f

自定義控件-多個控件到一組中

logs pub name 添加多個 tool 是否 imp efi 類名 dmwidgetinterface.h 1 #ifndef _DM_WIDGET_INTERFACE_H_ 2 #define _DM_WIDGET_INTERFACE_H_ 3 4

[Winform]setupfactory打包開機自啟動的腳本

自啟動 如何 var version col src idt span 開機自啟 摘要 如果有這樣的需求,需要軟件開機自啟動,該如何做呢?開機自啟動的做法,就是修改註冊表,將你的exe註冊到註冊表Run節點下。 setupfactory 在安裝的時候需要以管理員身份運

最近感想+用shell腳本新建文件創建的註釋

網易雲 string 上班 amp 吸引 都是 2017年 現象 保持 離職了將近20天了,帶著女朋友回家見了下家長,過了個國慶節,5號返深。當時離職的原因是,對工作現狀不滿(工資待遇低,倒掛),對工作內容積極性不高(興趣不深、沒有成就感),導致這種現象的原因,我分析了下歸

jquary中的創建節點節點的方法

子元素 span 關於 .com href 百度一 clas script pre 今天來說一下針對jquary關於創建節點和添加節點的方法,先來看看創建節點: 1、直接添加節點內容即可 $("div").append(‘<a href="http://www.

01 Maven構建的項目中,把.xml等配置文件到編譯目錄

build 文件 構建 main %20 sources 更新 目錄 如果 Maven構建的項目,默認只會把src/main/resources目錄下的xml配置文件添加到編譯目錄。 如果需要把src/main/java目錄下的xml配置文件也添加到編譯目錄,需要在pom.

全網最詳細的hive-site.xml配置文件裏<name>hive.cli.print.header</name>和<name>hive.cli.print.current.db</name>前後的變化(圖文詳解)

xml配置 note 個人博客 default 詳情 公眾 class 人生苦短 CA   不多說,直接上幹貨!     比如,你是從hive-default.xml.template,復制一份,改名為hive-site.xml     一

jqGrid---單元格回車事件(afterSaveCell)

1專案需求:有一個jqGrid的一列,在該列的單元格輸入完,按回車後,觸發某個事件。 afterSaveCell事件 afterSaveCell(rowid,name,val,iRow,iCol) rowid:行id name:列名稱 val:修改後的單元格的值 iRo

Java 對JTextField回車響應

問題:       在程式設計的時候,總會遇到這樣的問題       需要在JTextField文字框框中添加回車響應       即:鍵盤按下回車鍵,等同於滑鼠單擊按下一個Button按鈕,並進行事件操作 程式碼: JFrame frame = new JFrame()

C# Winform打包部署註冊表資訊實現開機啟動

      使用VS自帶的打包模組可以很方便的對專案進行打包部署,同時我們也可以在安裝部署時操作登錄檔實現開機啟動軟體。具體實現如下: 建立安裝部署這部分就不用說了,新增安裝部署專案後,滑鼠右鍵安裝專案->檢視->登錄檔, 要使軟體在開機就執行,可以在HKEY_C

html頁面中回車事件

<SCRIPT ID=clientEventHandlersJS LANGUAGE=javascript> function document_onkeypress() {     

easyUI樹形節點點擊和動態Tab

exists 點擊 als selected select tool abs pan gets var index = 0; function addPanel(url,title){ if(!$(‘#tt

easyUI樹形節點點擊和動態Tab-

expand tools text addtab 如果 tracking 參數 true 樹形結構 easyUI是一種基於jQuery的UI框架,可以直接閱讀官網的API教程學習,最近做的項目要用到這個框架,就一邊看一邊做,先看一下動態添加Tab,實際項目中我

jquery點擊li標簽之後在該li標簽上一個class,點擊下一個li刪除上一個li的class

style 下一個 div mov 元素 使用 font rem pre 思路:點擊當前li元素後是用removeClass()刪除所有兄弟元素(使用siblings()獲取)的class樣式,然後使用addClass()為當前li添加class 具體演示如下: 1、HTM

Pycharm在創建py文件,自動文件頭註釋

文件頭 images image nbsp 輸入 pycha -1 img .com 操作如上圖所示,一般輸入的註釋為: Pycharm在創建py文件時,自動添加文件頭註釋

每天一個JS 小demo之個人信息。主要知識點:DOM操作中的表格操作,節點操作

mov src i++ blog this tex set elements img 以下是簡易效果: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8">

tomcat 服務不支持 chkconfig 以及其他服務不能到開機啟動的操作

支持 bin 服務 啟動 tomcat chmod 報錯 但是 列表 在安裝完tomcat後想添加的開機自啟動的操作,但是報錯tomcat 服務不支持 chkconfig,後來在 /etc/init.d/tomcat中的#!/bin/bash後添加上#chkconfig:

在末尾節點案例

body 末尾 技術分享 添加節點 pre rip button cli .get 在末尾添加節點案例 步驟 1、獲取到ul標簽2、創建li標簽 document.createElement("標簽名稱");3、創建文本 document.createT

grid安裝asm磁盤candidate沒有分區盤

ida dev .cn all 解決 格式化 共享 再次 png 今天在虛擬機上做rac雙機。用udev來做的磁盤規則。安裝grid一路很順利完成。之後想再次練習grid安裝,就將兩臺rac的虛擬機還原了,但存儲的機器沒動,共享的硬盤也沒動。然後再次安裝grid 之後問

Dom4j解析語音數據XML文檔(註意ArrayList多次對象,會導致覆蓋之前的對象)

value exc 根節點 屬性 repl 叠代器 信息 ledir gettext 今天做的一個用dom4j解析聲音文本的xml文檔時,我用ArrayList來存儲每一個Item的信息,要註意ArrayList多次添加對象,會導致覆蓋之前的對象;解決方案是在最後將對象添加