• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 使用 LibXML2 處理配置文件

    發表于:2007-05-25來源:作者:點擊數: 標簽:
    學習如何在您的 UNIX 應用程序中使用 XML(可擴展標記語言)。本文面向那些不熟悉 XML 的 UNIX 開發 人員,研究了 Gnome 項目中開發的 XML 庫。在從總體上對 XML 進行簡單的解釋之后,您將看到 UNIX 應用程序開發人員可能用來解析和管理 XML 格式的配置文件
    學習如何在您的 UNIX® 應用程序中使用 XML(可擴展標記語言)。本文面向那些不熟悉 XML 的 UNIX 開發人員,研究了 Gnome 項目中開發的 XML 庫。在從總體上對 XML 進行簡單的解釋之后,您將看到 UNIX 應用程序開發人員可能用來解析和管理 XML 格式的配置文件的示例代碼,其中使用了 LibXML2 庫。

    引言

    要創建完善的、高度互操作性的應用程序,XML 是一個很好的選擇,因為它正越來越廣泛地應用于數據存儲和配置文件管理。本文研究了一個使用 XML(可擴展標記語言)作為其配置文件格式的示例應用程序,并通過該示例向您介紹如何在自己的 UNIX 應用程序中使用 XML。該示例應用程序使用 Perl 編寫,并且其中使用了基于 Gnome 項目的 LibXML2 庫的 Perl 模塊。

    在給出 XML 的簡單定義之后,本文介紹了一個使用 XML 編寫的示例配置文件。然后,通過示例代碼來介紹如何解析這個配置文件。系統管理員可以手動修改該配置文件,但通常在一定程度上,需要應用程序直接地修改該配置文件。然后,本文通過一個示例介紹如何以編程的方式向這個 XML 文檔添加新的配置選項,以及如何修改當前條目的值。最后,本文介紹了將這個經過修改的配置文件寫入到磁盤的代碼。





    回頁首


    關于 XML

    在開始研究 LibXML2 庫之前,讓我們先來鞏固一下 XML 的相關基礎。XML 是一種基于文本的格式,它可用來創建能夠通過各種語言和平臺訪問的結構化數據。它包括一系列類似 HTML 的標記,并以樹型結構來對這些標記進行排列。

    例如,可參見清單 1 中介紹的簡單文檔。這是配置文件部分中研究的配置文件示例的簡化版本。為了更清楚地顯示 XML 的一般概念,所以對其進行了簡化。


    清單 1. 一個簡單的 XML 文件
    <?xml version="1.0" encoding="UTF-8"?>
                <files>
                <owner>root</owner>
                <action>delete</action>
                <age units="days">10</age>
                </files>
                

    清單 1 中的第一行是 XML 聲明,它告訴負責處理 XML 的應用程序,即解析器,將要處理的 XML 的版本。大部分的文件使用版本 1.0 編寫,但也有少量的版本 1.1 的文件。它還定義了所使用的編碼。大部分文件使用 UTF-8,但是,XML 設計用來集成各種語言中的數據,包括那些不使用英語字母的語言。

    接下來出現的是元素。一個元素以開始標記 開始(如 <files>),并以結束標記 結束(如 </files>),其中使用斜線 (/) 來區別于開始標記。

    元素是 Node 的一種類型。XML 文檔對象模型 (DOM) 定義了幾種不同的 Nodes 類型,包括 Elements(如 files 或者 age)、Attributes(如 units)和 Text(如 root 或者 10)。元素可以具有子節點。例如,age 元素有一個子元素,即文本節點 10。而 files 元素有七個子元素。其中三個很明顯。它們分別是三個子元素:owner、actionage。其他四個分別是元素前后的空白文本符號。

    XML 解析器可以利用這種父子結構來遍歷文檔,甚至修改文檔的結構或內容。LibXML2 是這樣的解析器中的其中一種,并且文中的示例應用程序正是使用這種結構來實現該目的。對于各種不同的環境,有許多不同的解析器和庫。LibXML2 是用于 UNIX 環境的解析器和庫中最好的一種,并且經過擴展,它提供了對幾種腳本語言的支持,如 Perl 和 Python。

    作為研究工作的第一步,讓我們先來看一個示例配置文件。





    回頁首


    配置文件

    文中的示例應用程序讀取了特定文件的操作列表。而配置文件定義了這些文件和操作。假設該配置文件是位于 UNIX 文件系統中某個位置的一個文件。例如,在 UNIX 系統 cron 中可能會使用這個配置文件。該 XML 文件定義了目錄路徑和根據條件要執行的操作,而這些條件則包括所有者和文件存在時間(請參見清單 2)。


    清單 2. 配置文件
    <?xml version="1.0" encoding="UTF-8"?>
                <filesystem>
                <path>
                <dirname>/var</dirname>
                <files>
                <owner>root</owner>
                <action>delete</action>
                <age units="days">10</age>
                </files>
                <files>
                <owner>any</owner>
                <action>delete</action>
                <age units="hours">96</age>
                </files>
                </path>
                <path>
                <dirname>/tmp</dirname>
                <files>
                <owner>any</owner>
                <action>delete</action>
                <age units="hours">24</age>
                </files>
                </path>
                </filesystem>
                

    在本例中, 元素是 filesystem,它包含兩個 path 元素。每個 path 元素包含相應的目錄名和一個或多個 files 元素。每個 files 元素通過 age 元素的 units 屬性中指定的存在時間單位,定義了當用戶或用戶文件達到特定的存在時間時,應用程序應采取的操作。請記住,空白符號是有意義的。從結構的觀點來看,每個空白符號組成了獨立的 Text 節點。

    在產品環境中,一個編寫完善的 UNIX 應用程序不僅應該具有讀取數據并對其進行操作的能力,而且還應具有根據用戶輸入對數據進行添加、刪除和修改的能力。

    現在讓我們來研究使用該數據的應用程序。





    回頁首


    示例程序

    本文余下的內容通過示例代碼介紹對 XML 配置文件的解析和管理。這些示例逐一地讀取并修改配置文件,但在 UNIX 開發人員的日常工作中,您可以在任何類型的任務中使用這些概念。而且,因為使用了 LibXML2 庫,所以您可以將這些概念插入到幾乎任何的 UNIX 應用程序中。

    我們將在本文中介紹使用 Perl 版本的 LibXML2 庫的示例。Internet 上的大部分文檔都在討論如何使用 Java™ 或 Microsoft® Visual Studio 工具進行編程,但對于 UNIX 用戶或開發人員來說,Perl 則更有價值。清單 3 顯示了解析該 XML 文檔所需的 Perl 模塊。


    清單 3. 需要的庫
    XML::LibXML
                XML::LibXML::Common
                XML::NamespaceSupport
                XML::SAX
                

    下面部分中介紹的代碼僅僅只是一個框架??煞秩齻€部分對其進行介紹:解析、操作和導出。

    在加載和解析階段中,可能會將數據加載到 Perl 變量中,如列表或哈希,但由于每個程序員都有他/她自己首選的方法來完成這項任務,所以我們把它留給讀者作為一項練習。下面的代碼只是簡單地顯示了數據,以此說明該腳本正確地找到了相應的數據。

    在操作階段中,該程序對 XML 文檔中的元素進行添加、修改和刪除的數據更新操作。通常地,這將按照用戶的操作來進行。

    最后在導出階段中,將經過修改的最終的文檔寫回到磁盤。





    回頁首


    加載和解析數據

    對于應用程序來說,讀取 XML 文件的第一步是加載該數據并將其解析為一個 Document 對象。在此基礎上,可以對 DOM 樹進行遍歷以獲取特定的節點。讓我們來看看清單 4 中的代碼是如何完成該任務的。


    清單 4. 加載和解析 example.xml 的代碼
    my $parser = XML::LibXML->new();
                my $doc = $parser->parse_file("example.xml");
                $filesystem = $doc->getDocumentElement();
                @nodes=$filesystem->childNodes;
                foreach $node (@nodes) {
                if($node->nodeType==ELEMENT_NODE) { # ignore text nodes
                # just get the first match
                @dirnames = $node->getElementsByTagName("dirname")->item(0);
                foreach $dirname (@dirnames) {
                print "dirname: " . $dirname->textContent . "\n";
                # push this into an array
                }
                # get all children
                @files = $node->getChildrenByTagName("files");
                foreach $file (@files) {
                foreach $values ($file->childNodes) {
                # ignore text nodes
                if($values->nodeType!=XML_TEXT_NODE) {
                if($values->nodeName() eq "age") {
                # check for attribute, otherwise, use default of 'hours'
                if($values->hasAttributes()) {
                print $values->nodeName() . ": " .  $values->textContent;
                print " " . $values->attributes->item(0)->value();
                print "\n";
                } else {
                print $values->nodeName() . ": " .  $values->textContent;
                print " hours\n";
                }
                # calculate extended value from units and put in a
                # hash linked with this dirname, etc.
                } else {
                print $values->nodeName() . ": " .  $values->textContent;
                print "\n";
                # put this value into a hash linked with $dirname.
                # We may have multiple entries for each $dirname, so
                # perhaps use an array within a hash
                }
                }
                }
                }
                }
                }
                

    首先,在清單 4 中,創建了解析器并將 XML 從文件加載到 XML::LibXML::Document 變量。這個對象包含了整個 XML 樹,并且具有與之關聯的各種方法可用來搜索節點、導出、驗證和創建新的節點。本文將在后面的幾個部分中對其中的一些方法進行介紹。從代碼的起始處開始,您可以看到 getDocumentElement() 方法,它用于返回文檔的根節點。從這個根節點,就可以遍歷整個 XML 樹。

    foreach 循環對父 filesystem 元素中的每個節點進行循環。當僅選擇元素節點時,該循環將得到 path 元素。getElementsByTagName() 方法根據相應的名稱在節點中搜索對應的元素,并通過 NodeList 對象返回它們。每個 path 元素包含了一個 dirname 元素,所以代碼搜索名稱為 dirname 的元素,并獲取其中的第一個條目。在代碼中只能選擇 ELEMENT 類型的節點,因為該方法不支持 TEXT 節點,并且會在 Perl 中產生一個不可恢復的錯誤。

    在一個 path 元素中可能存在多個 files 元素,所以代碼對 getChildrenByTagName() 方法的每一個元素進行循環,這個方法類似于 getElementsByTagName(),但僅搜索目標節點的直接子節點。這將返回所有的 files 元素,但必須進行進一步的解析以獲得 owner、actionage 元素。在得到了這些節點之后,可以調用 textContent 以從相應的元素中獲取實際的值。下面顯示的是選擇 ELEMENT 節點孩子的 TEXT 節點值的快捷方法:

    print $values->nodeName() . ": "
                print $values->firstChild()->nodeValue();
                

    在使用 age 元素的情況下,還可以通過一個屬性來指定時間單位。使用 hasAttributes()Attributes 函數,該程序可以提取相應的屬性,如果它存在話。如果它不存在,那么該程序使用缺省值 hours。

    現在讓我們來介紹對數據的操作,這樣就能夠以編程的方式來添加、刪除和編輯操作。





    回頁首


    對數據進行操作

    現有的代碼本身就是一個有用的程序。用戶可以很容易地以手動地方式對該 XML 文件完成程序所做的修改。然而,有經驗的 UNIX 開發人員還可以使用 XML 函數在程序中直接對文件進行修改。例如,可以包含用于添加新的操作或刪除現有操作的菜單選項。要實現這個目的,讓我們來看看在程序中對數據進行操作的代碼。


    清單 5. 向文檔添加填充的 path 節點
    $newnode = $doc->createElement("path");
                $newdirnode = $doc->createElement("dirname");
                $newdirnode->appendText("/root");
                $newfilesnode = $doc->createElement("files");
                $newownernode = $doc->createElement("owner");
                $newownernode->appendText("any");
                $newactionnode = $doc->createElement("action");
                $newactionnode->appendText("archive");
                $newagenode = $doc->createElement("age");
                $newagenode->appendText("30");
                $newagenode->setAttribute("units","days");
                $newfilesnode->addChild($newownernode);
                $newfilesnode->addChild($newactionnode);
                $newfilesnode->addChild($newagenode);
                $newnode->addChild($newdirnode);
                $newnode->addChild($newfilesnode);
                $filesystem->addChild($newnode);
                

    清單 5 中的代碼創建了一個 path 元素,并為其填充了所有的元素。然后,將這個新創建的節點添加到根元素,即 filesystem。需要使用 XML::LibXML::Document 類的 createElement() 方法來創建每個元素。(正是 Document 創建了您所需要的任何新的節點。)該方法返回一個尚未連接到文檔樹中任何位置的空節點。然后可以使用 XML::LibXML::Element 類的 appendText() 方法為每個節點添加內容。此外,相對于創建一個新的 TEXT 節點,然后對其進行填充并將其添加到相應的元素,這是一種快捷的方法??梢允褂?setAttribute() 方法來添加屬性,如果在目標元素中不存在給定名稱的屬性,該方法將自動創建一個新的 ATTRIBUTE 節點。

    在完成每個節點的創建并分別對它們進行了填充之后,可以使用要求的子節點作為參數,對父節點調用 addChild() 方法。因此在上面的代碼中,$newownernode 成為了 $newfilesnode 的子節點。文檔中所有的節點保持其添加時的順序。如果您希望指定其他的順序,可以使用 insertAfter()insertBefore() 函數。

    將每個節點添加到相應的父節點,直到最后將主父節點添加到已經存在于文檔中的一個節點。在上面的示例中,將該節點添加到了 filesystem 根節點。(如果您是從頭開始創建該文檔,那么可以對 Document 對象本身調用 addChild() 來添加根元素,然后再向該元素添加任何其他的節點。)

    正如前面所解釋的,清單 2 中的示例 XML 代碼是一種可讀的格式。換行和縮進使得文檔更容易閱讀。XML 解析器將讀取所有這些字符,并將其作為一個 TEXT 類型的節點。清單 5 中的示例沒有添加任何這樣的 TEXT 節點。因此,該示例的輸出將不包含任何換行或縮進。如果您希望創建這種空白字符,那么需要使用 XML::LibXML::Text 類來創建 TEXT 類型的節點,或者使用該文檔對象的 createTextNode() 函數。該構造函數的返回值是一個節點,可以使用與上面示例中相同的方式將其添加到樹中。

    要更改文件的內容,可以直接設置相關 TEXT 節點的 nodeValue(),或者替換整個元素:

    $newnode = $doc->createElement("owner");
                $newnode->appendText("toor");
                $oldnode->replaceNode($newnode);
                

    要刪除一個節點,有以下幾種選擇。一種方法是僅將其從結構中刪除,代碼如下所示:

    $file->unbindNode();
                

    在找到需要刪除的節點之后,通過一行命令即可將其從結構中刪除,但并沒有從文檔中刪除。這個函數調用直到程序結束時才真正銷毀該數據結構。如果您需要將節點移動到樹中的其他部分,那么可以使用相同的變量來調用 addNode() 以將其重新添加到文檔中新的位置。您還可以使用 removeChild()removeChildNodes() 函數,這樣可以從文檔中徹底地釋放相應的資源。





    回頁首


    保存 XML 文件

    在一些編程語言中,將 XML 文檔保存到文件中可能比較煩瑣,但幸運的是,LibXML 讓這項任務變得非常簡單:

    $doc->toFile("example.xml");
                

    在對數據進行的所有的操作中,這是最簡單的一種操作。在對內存中的 XML 文檔完成了相應的修改之后,只需使用一個函數調用就可以將其寫回到對應的配置文件中。還可以使用相關的 Perl 函數,如 toString()toFH(),這些函數分別將 XML 輸出到一個字符串變量或者一個已打開的 Perl 文件句柄,而文件句柄將為您的應用程序的構建帶來更大的靈活性。





    回頁首


    結束語

    通過提供 LibXML2 庫以及對 Perl 模塊的支持,Gnome 項目完成了一項很有價值的任務。本文對管理和使用 XML 配置文件所需要的三個重要的步驟進行了介紹。解析階段可能是最復雜的,因為它需要一定程度的遞歸設計來解析 XML 樹。盡管有些煩瑣,但對內存中 XML 文檔的操作卻是非常簡單明了的。使用 LibXML2 庫導出經過修改的配置,也是非常容易的。

    盡管相對于標準的UNIX 思維方式來說,需要進行一定的思維模式轉移,但是 XML 可以為數據管理提供一種功能強大的方法。與簡單的數據庫格式相比,樹型結構提供了更加靈活的數據視圖。在開發新的應用程序或修改舊的應用程序時,可將其規范化為使用 XML 配置文件,在進行規范化的過程中可以很容易地使用 Gnome 項目所提供的免費的標準庫,正如本文所介紹的。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>