澳门新葡亰娱乐官网PHP静态分析与跨站脚本检测(三)

以下是自家看Pixy中有些顺序的笔录,主借使为着未来能够相比快速的知情程序的思绪,记录下来,要不然那么多东西光靠脑子怎么行。有的地方或然持有疏漏,小编自个儿望着恐怕都感到不太好。

版式本历史


Revision 1 June 4, 2002

ProgramConverter- convert(卡塔尔首先使用PhpParser创设一棵parseTree,不过那棵tree只在那运用而已。利用这棵tree、输入文件甚至ProgramConverter对象自己建设布局TacConverter对象baseTac,然后调用baseTac.convert(卡塔尔国。这一个baseTac正是能够由此本对象回来的TacConverter属性。然后通过baseTac.getIncludeNodes(卡塔尔国获得必要管理的被含有文件。
步向while循环,前提是函数内局地变量goOn为true和未有-w参数。该while循环命名叫,设置goOn=false。借使急需管理的包罗文件链表不为空,踏向第贰个while循环。通过for循环将具有的CfgNodeInclude结点单独提抽出来,假若那一个node是内需跳过的,就取下几个node;如若不是一贯通过常量满含文件的话,就继续取下二个,这个人展览馆示不管理;借使上述两条都不满意,调用include(卡塔尔(قطر‎方法,再次来到二个里边枚举类型IncStatus,重设将在管理链表,继续w2*。使用baseTac管理一下过后,假设不设有non-literal
includes就跳出w1*。不然,初阶拍卖non-literal
includes。。使用baseTac中获得的有所办法,包罗客商方法和Main方法计算。建立AliasAnalysis对象,并以之当作参数创立LiteralAnalysis对象,调用analyze(卡塔尔国领头深入分析。然后,获取包罗结点设置为就要管理的盈盈文件链表,步入for循环,排查实验,倘使已经济检察测过,跳过,不然即为non-literal的富含文名,按准则分别管理。在通过this.include(State of Qatar方法的重回值决定for循环的去向。再经过this.baseTac.assignFunctions(卡塔尔,然后再度安装需求管理的蕴藏链表,继续w1*。
将事情发生在此以前获得的只怕会使得的蕴藏文件列表中其实并没有用的都去掉。并将literalAnalysis置为null,以节省里部存款和储蓄器。纵然须求采取AliasAnalysis,作出相应处理,不然,利用baseTac调用replaceGlobals(卡塔尔,将兼具函数的一对变量使用相应的全局变量替换,举办type深入分析,与日前的literal进度剖判大致。然后将functions转变为CfgNode,然后输出总计音信。释放能源,调用baseTac.addSuperGlobalElements(State of Qatar加多全局成分,将节点倒序排列。-
include(卡塔尔得到应该包括的公文,如若文件不真实,重临NOTFOUND。不然,在allFiles中加多该公文,并将含有与被含有增添到includeGraph中,倘若加多建功立业,对被含有的文本创设parseTree,并确立TacConverter对象,不过此地的靶子都只是用来检查测验里边的include,并将那一个CfgNodeInclude增添进从convert(卡塔尔传过来的weComeAfterwards中,以待管理。那样将goOn=true,循环检查实验。

发端草案


Revision 2 June 12, 2002

CfgEdge
inEdges对于CfgNodeIf来讲,是指决断规范,而outEdges是结果。对于其余的node有一点说不清楚。

日增查找属性值


Revision 3 Aug. 31, 2002

InterAnalysis
从这一个程序看,将被围观文件解析之后,得到的要紧是TacConverter,由她收获TacFunction,然后再拿走CfgNode,三个CfgNode对应三个Context,二者一齐整合InteWorkListElemnt。在InterAnalysisInfo中则是每一个Cfgode对应三个InterAnalysisNode,在这里个node中,由原先与刚才CfgNode对应的Context对应贰个LatticeElement,而Latticelement则分别存放相应的音信。如AliasLatticelement贮存MustAliases和MayAliases,而DepLatticeElement则寄存TacPlace、DepSet、Vatiable等。
对于test.php来讲,通过initTransferFunction(State of Qatar时,在ProgramConverter.convert(State of Qatar中生出了TransferFunctionId,而在checker.analyzeTaint(卡塔尔国中则还获得了ConpositeTransferFunction。此时,每种InterAnalysisNode所包罗的TransferFunction是显然了的实例,因此下边的transfer方法调用时会调用相应的实例的措施。对于本例,由于TransferFunctionId.transfer(卡塔尔重返的是流传的参数本身,故调用transfer之后获取的outValue与inValue是一律的。仅出现在当analyze(卡塔尔中node为后便三种的时候,第一种未有动用outValue,第二种直接使outValue
= inValue。- initGeneric(State of Qatar后面包车型的士interAnalysisInfo(卡塔尔国怎么就有长度了,没搞掌握。通过initTransferFunction(卡塔尔国好像能够将genericAnalysisInfo增多数码,试验中是二十三个。不过interAnalysisInfo也是二十多少个。因该是那样的,二者指向同一个内部存款和储蓄器地址,对genericAnalysisInfo加多从头到尾的经过,就使得interAnalysisInfo也可以有了一致的内容。-
analyze (卡塔尔国 那个措施主若是针对不相同的node选用分裂的艺术。首要分为了5类node

修改释放内存

  • CfgNodeCall – CfgNodeExit – CfgNodeIf – CfgNodeCallRet – 其余通过inValue调换得到outValue,然后拿走node的全部outgoing的边(outEdges卡塔尔,将每条边的顶点节点即node的后代successor得到,然后经过当前的context和刚到手的outValue、successor协作增殖,向analysisNode设置新的
    PhiValue,并向workList中增添InterWorkListElement。这里小编知道propagate是产生叁个InterWorkListElement,因为在analyze中运用的是它。
    在analyze(卡塔尔(قطر‎刚伊始的时候,workList中唯有一个因素InterWorkListElement(this.mainHead,
    this.mainContext卡塔尔国。
    analyze(卡塔尔(قطر‎中通过analysisNode取得的LatticeElement由test.php第叁遍在ProgramConverter.convert(卡塔尔国中时都以TypeLatticeElement,而在Checker中analyzeTaint(卡塔尔国时则全部是DepLatticeElement。通过调用dump方法能够,前多少个的结果即placeToDep为空,而后便则打字与印刷出全体Map。-
    propagate(Context context, LatticeElement value, CfgNode target)在analyze(卡塔尔国中超级多状态下调用都以(当前context,outValue,successor卡塔尔国通过target获得InterAnalysisInfo中对应的analysisNode,不为null的话,通过context获得target的oldPhiValue,假使oldPhiValue=null,则将其设为全部LatticElementd的上马值,实际上也是null。假若value==oldPhiValue,则表明值未有改观,能够再次来到了。不然,在lattice中应用value和oldPhiValue总结一个newPhiValue,假如那一个newPhiValue与oldPhiValue差别,则将其安装为target的Phivalue,并在workList中增多一个InterWorkListElement以便analyze(卡塔尔中一而再剖判。

Revision 4 Nov. 10, 2002


充实编码内容斟酌

DepClient – collectSinks(卡塔尔国对于test0225.php来讲,对XSS检验获得的functions数目为2,可是sinks数目为5;对SQL检查实验functions数目为2,sinks数目为1。
首先通过depAnalysis实例获得全体的TacFunction,然后对于每一个TacFunction取得Cfg之后对CfgNode排序然后每一个检验。
获得的TacFunction有八个分别为:_main和foo,里边包括的CfgNode分别是19个和3个。而对于XSS检查实验有5个sink,均为echo,这里不管是不是会时有产生XSS,均作为sink再次来到。

Revision 5 Dec. 15, 2002

  • findDangerousUninit(DepGraph relevant卡塔尔国 首先寻找relevant中的uninit
    nodes,结果展现在上多个艺术中XSS的5个sink中,后多少个重回结果都为空。对于不为空的uninitNode,则是找寻其父节点Predecessor,要是父结点不为1个,则抛出至极,否则抽取那一个父结点,切磋三种情况:
  • DepGraphOpNode 直接确定为evil function重回。 – DepGraphNormalNode
    调用initiallyTainted(State of Qatar方法查看再次来到值,即便为ALWAYS或许IF凯雷德G,则认为是evil
    function,重临。 – initiallyTainted(TacPlace place卡塔尔国这里place思索三种情景: – Constant
    这种状态下,直接就认为不容许是tainted,再次回到NEVELX570 – Variable 又分二种情况
  • superglobals
    在一些特定情景下以为是harmless,其他都以唯恐危机的。详见DepClient.java –
    non-superglobals 同上。然而一些跟命令行-g选项关于。 – others
    都感到是重伤的。

更加多释放内部存款和储蓄器内容改变


Revision 6 Jan. 26. 2003

TacConverter – start(卡塔尔通过传播的PhpTree的root创立起多个CfgNode,作为Cfg的root和exit,然后将tree中的种种node连接起来,将phptree转换来Cfg。

增多索引


Revision 7 April 25, 2003

有关上文中涉及的test0225.php,文件如下:?phpfunctionfoo(State of Qatar{$var=$_GET[”evil”];return$var;}//$a=$_GET[”evil”];$b=foo();//$a=5;//echo$a;echo$b;//$ais6hereecho$_GET[”a”];echo$e;$x=explode(”_”,$get);mysql_query($x[0]);if(true)echoABCD;if($a==”a”$c==”d”)echodfg;?<

增进编写翻译附录

Revision 8 July 24, 2003

添加Xpath例子

Revision 9 Feb. 14, 2004

订正Xpath例子中的BUG

目录

绪论…………………………………………………………………….
2

数据类型 ……………………………………………………………………..
2

浅析文件 …………………………………………………………………
2

获得成分内容 ………………………………………………….
3

接受Xpath获得元素内容 …………………………………. 4

写元素 ……………………………………………………… 6

写属性 ………………………………………………………………
6

得到属性 ………………………………………………………….
7

编码调换 ………………………………………………………….
7

A. 编译 …………………………………………………………………
9

B. 示例文书档案 ………………………………………………………….
9

C. Keyword例程代码………………………………………………
9

D. XPath例程代码………………………………………………..
10

E. 增加属性例程代码………………………………………. 11

F 增添keyword例程代码………………………………………. 13

G. 得到属性值例程代码……………………….. 14

H. 编码转换例程代码…………………………….. 15

I. 感谢……………………………………………………….
16

摘要

Libxml是一个有无需付费许可的用于拍卖XML、能够轻巧超越八个平台的C语言库。那几个指南提供它的主导函数的例证。 

 

绪论

Libxml是叁个得以完成读、创造及操纵XML数据功用的C语言库。那几个指南提供例子代码并付出它根底能的批注。.

在这里个类其他主页上有Libxml及越多关于它可用的材质。包涵有完整的API文书档案。那一个指南并不能够庖代这一个完整的文书档案,可是证明功用须求使用库来完结基本操作。

那几个指南基于八个大致的XML应用,它利用自家写的一篇小说生成,它满含有元数据和小说的重点。

本指南开中学的例子代码示范怎么产生:

• 剖析文书档案

• 得到内定成分的文本

• 加多叁个要素及它的源委

• 增多壹本性能

• 得到四个本性的值

事例的完全代码包蕴在附录中

 

数据类型

Libxml定义了累累数据类型,大家将再三蒙受它们,它隐敝了凌乱的源点引致你不用项理它只有你有特定的急需。

xmlChar
 代替char,使用UTF-8编码的一字节字符串。倘让你的数量应用别的编码,它必需被转变来UTF-8技艺应用libxml的函数。在libxml编码帮衬WEB页面有更加多关于编码的有用新闻。

XmlDoc 包括由拆解深入分析文书档案建设结构的树构造,xmlDocPtr是指向那几个布局的指针。

xmlNodePtr and
xmlNode 包涵单一结点的布局xmlNodePtr是指向那些组织的指针,它被用于遍历文书档案树。

 

深入分析文档

解析文书档案时独自需求文件名并只调用三个函数,并有荒谬检查。完整代码:附录C,
Keyword例程代码 

 

①xmlDocPtr doc;

②xmlNodePtr cur;

③doc = xmlParseFile(docname);

④if (doc == NULL ) {

fprintf(stderr,”Document not parsed successfully. /n”);

return;

}

⑤cur = xmlDocGetRootElement(doc);

⑥if (cur == NULL) {

fprintf(stderr,”empty document/n”);

xmlFreeDoc(doc);

return;

}

⑦if (xmlStrcmp(cur->name, (const xmlChar *) “story”)) {

fprintf(stderr,”document of the wrong type, root node != story”);

xmlFreeDoc(doc);

return;

}

①定义解析文档指针。

②定义结点指针(你必要它为了在挨门挨户结点间活动卡塔尔(قطر‎。

④反省深入解析文书档案是不是成功,如若不成功,libxml将指三个报了名的荒谬并终止。

 

注释

多少个分布错误是不确切的编码。XML规范文书档案除了用UTF-8或UTF-16外还可用其余编码保留。假诺文书档案是如此,libxml将电动地为您转移到UTF-8。越来越多关于XML编码音信包括在XML规范中。

⑤赢得文书档案根成分

⑥反省确认当前文书档案中隐含内容。

⑦在这里个例子中,大家须求料定文书档案是科学的品类。“Story”是在这里个指南开中学采用文书档案的根类型。

 

收获成分内容

 

您找到在文书档案树中你要索求的要素后方可博得它的从头到尾的经过。在这里个例子中大家搜索“story”成分。进程就要冗长的树中查找大家感兴趣的要素。我们假准时你早就有了二个名称叫doc的xmlDocPtr和三个名叫cur的xmlNodPtr。

①cur = cur->xmlChildrenNode;

②while (cur != NULL) {

 

  

 

if ((!xmlStrcmp(cur->name, (const xmlChar *)”storyinfo”))){

parseStory (doc, cur);

}

cur = cur->next;

}

 

①取得cur的率先个子结点,cur指向文书档案的根,即“story”成分。

②以此循环迭代通过“story”的子成分查找“storyinfo”。那是多个富含有大家将追寻的“keywords”的要素。它利用了libxml字符串比较函数xmlStrcmp。如果切合,它调用函数parseStory。

 

void

parseStory (xmlDocPtr doc, xmlNodePtr cur) {

xmlChar *key;

①cur = cur->xmlChildrenNode;

②while (cur != NULL) {

if ((!xmlStrcmp(cur->name, (const xmlChar *)”keyword”))) {

③key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);

printf(“keyword: %s/n”, key);

xmlFree(key);

}

cur = cur->next;

}

return;

}

①再一次获得第一身长结点。

②像上面十三分循环相像,大家能过迭代,查找我们感兴趣的名称为“keyword”的要素。

③当我们找到成分“keyword”时,我们供给打字与印刷它含有在XML中的记录的源委,文本被含有于元素的子结点中,由此大家借助了cur->xmlChildrenNode,为了得到文本,我们应用函数xmlNodeListGetString,它有贰个文书档案指针参数,在此个事例中,我们独有打字与印刷它。

注释

因为xmlNodeListGetString为它回到的字符串分配内存,你必须利用xmlFree释放它。

 

运用X帕特h得到成分内容

除了一步步遍历文书档案树查找成十分,Libxml2饱含帮助使用Xpath表明式得到内定结点集。完整的Xpath
API文书档案在那。Xpath允许通过路径文书档案寻找匹配内定条件的结点。在下边包车型客车事例中,大家探索文书档案中颇负的“keyword”成分。 

 

 

注释

上边是Xpath完整的评论。它详细的利用质地,请查阅Xpath规范。

其一例子完整的代码参见附录D,XPath例程代码。

Using XPath requires setting up an xmlXPathContext and then supplying
the

XPath expression and the context to the xmlXPathEvalExpression function.

The function returns an xmlXPathObjectPtr, which includes the set of

nodes satisfying the XPath expression.

应用XPath必要设置xmlXPathContext才支撑XPath表达式及xmlXPathEvalExpression函数,那个函数再次来到两个xmlXPathObjectPtr,它包涵有XPath表明式的结点集。

 

xmlXPathObjectPtr

getnodeset (xmlDocPtr doc, xmlChar *xpath){

①xmlXPathContextPtr context;

xmlXPathObjectPtr result;

②context = xmlXPathNewContext(doc);

③result = xmlXPathEvalExpression(xpath, context);

④if(xmlXPathNodeSetIsEmpty(result->nodesetval)){

printf(“No result/n”);

return NULL;

}

xmlXPathFreeContext(context);

return result;

}

①首先定义变量

②开头化变量context

③应用XPath表达式

④反省结果

由函数重回的xmlPathObjectPtr包含七个结点集和其他需求被迭代及操作的音信。在此个例子中我们的函数重回xmlXPathObjectPtr,大家运用它打字与印刷大家文档中keyword结点的剧情。这些结点集对象饱含在联谊(nodeNr卡塔尔国中的成分数目及二个结点(nodeTab卡塔尔(قطر‎数组。

 

①for (i=0; i < nodeset->nodeNr; i++) {

②keyword = xmlNodeListGetString(doc,

nodeset->nodeTab[i]->xmlChildrenNode, printf(“keyword: %s/n”,
keyword);

xmlFree(keyword);

}

①变量nodeset->Nr持有结点集兰秋素的数额。大家采纳它遍历数组。

②打字与印刷每种结点包罗的从头到尾的经过。

注释

Note that we are printing the child node of the node that is returned,
because

the contents of the keyword element are a child text
node.注意我们打字与印刷的是结点的子结点的重临值,因为keyword成分的内容是叁个子文本结点。 

写元素

写成分内容使用方面超级多相同的步骤—深入分析文书档案并遍历树。大家先解析文书档案然后遍历树查找我们想插队成分的岗位。在那么些事例中,大家再一回搜索“storyinfo”成分并插入三个keyword。然后大家装文件写入磁盘。完整代码:附录E,增加keyword例程

本例中第一的不如在于parseStory

void

parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {

①xmlNewTextChild (cur, NULL, “keyword”, keyword);

return;

}

①XmlNewTextChild函数增添一个脚下结点的新的子成分到树中

假使结点被增加,大家应该写文档到文件中。你是不是想给成分钦点叁个命名空间?你能增添它,在我们的事例中,命名空间是NULL。

 

xmlSaveFormatFile (docname, doc, 1);

 

先是个参数是写入文件的名,你注意到和大家刚好读入的文书名是雷同的。在这里个事例中,大家仅仅覆盖原本的公文。第二个参数是四个xmlDoc布局指针,第多个参数设定为1,保障在输出上写入。

 

写属性

写属性相通于给七个新因素写文本。在这里个事例中,大家将助长八个reference结点U讴歌MDXI属性到大家的文书档案中。完整代码:附录F,增多属性例程代码。

reference是story成分的叁个子结点,所以找到并插入新因素及其性质是不难的。一旦大家在parseDoc进行了不当检查,大家就要不利的职位加放大家的新因素。但进展事前大家必要定义二个早先我们不见过的数据类型。

 

xmlAttrPtr newattr;

 

我们也亟需xmlNodePtr:

 

xmlNodePtr newnode;

 

余下的parseDoc则和眼下同样,检查根结点是还是不是为story。要是是的,那我们领悟大家就要钦赐的职分增加大家的要素。 

 

①newnode = xmlNewTextChild (cur, NULL, “reference”, NULL);

②newattr = xmlNewProp (newnode, “uri”, uri);

 

①施用xmlNewTextChild函数添国三个新结点到当下结点地方。

就算结点被抬高,文件应像前边的例证将我们加多的因素及文件内容写入磁盘。

 

得到属性

赢得属性值肖似于前方大家获取叁个结点的文本内容。在此个例子中,大家将抽出大家在前一部分增加的U奇骏I的值。完整代码:附录G,得到属性值例程代码。

其一例子的开始步骤和近年来是临近的:剖析文书档案,查找你感兴趣的因素,然后进入二个函数完结钦赐的伸手职责。在这里个事例中,大家调用getReference。

 

void

getReference (xmlDocPtr doc, xmlNodePtr cur) {

xmlChar *uri;

cur = cur->xmlChildrenNode;

while (cur != NULL) {

if ((!xmlStrcmp(cur->name, (const xmlChar *)”reference”))) {

①uri = xmlGetProp(cur, “uri”);

printf(“uri: %s/n”, uri);

xmlFree(uri);

}

cur = cur->next;

}

return;

}

 

①      关键函数是xmlGetProp,它回到三个富含属性值的xmlChar。在本例中,大家无非打字与印刷它。

 

注释

万一您选用DTD定义属性的固定值或缺省值,这一个函数也将得到它。

 

编码调换

数据编码宽容难点是技术员新建普通的XML或一定XML时最广大的费劲。依照那边稍后的座谈来合计设计你的应用程序将救助您防止那几个困难。实际上,libxml能以UTF-8格式保存和调整各种多少

  

您的顺序选取其它的数额格式,比如大范围的ISO-8859-1编码,必需利用libxml函数调换成UTF-8。若是您想你的次序以除UTF-8外的其余编码情势输出也必须要做调换。

 要是能立见到效果能地改造数据Libxml将采用转变器。无调换器时,仅仅UTF-8、UTF-16和ISO-8859-1能够被充当外部格式使用。有调换器时,它能将从此外格式与UTF-8调换的任何格式均可采用。当前调换器帮助大概150种分裂的编码格式之间的相互影响调换。实际帮助的格式数量正在被达成。每三个得以完结在的转变器尽大概的支撑每一样格式。

 

警告

一个广泛错误是在此中数据差别的一些行使分化的编码格式。最普及的是状态是叁个接收以ISO-8859-1当做内部数据格式,结合libxml部分接纳UTF-8格式。结果是一个应用程序要面前境遇分裂地里面数据格式。一部分代码试行后,它或其余一些代码将接收曲解的数据。

本条事例布局叁个精简的文书档案,然后增添在命令行提供的剧情到根成分并行使合适的编码将结果输出到规范输出设备上。在这里个例子中,大家接纳ISO-8859-1编码。在指令输入的剧情将被从ISO-8859-1改变成UTF-8。完整代码:附件H,编码调换例程代码。

* *

蕴含在例子中的调换函数使用libxml的xmlFindCharEncodingHandler函数。

 

①xmlCharEncodingHandlerPtr handler;

②size = (int)strlen(in)+1;

out_size = size*2-1;

out = malloc((size_t)out_size);

③handler = xmlFindCharEncodingHandler(encoding);

④handler->input(out, &out_size, in, &temp);

⑤xmlSaveFormatFileEnc(“-“, doc, encoding, 1);

 

①定义多少个xmlCharEncodingHandler函数指针。

②XmlCharEncodingHandler函数内需付出输入和输出字符串的抑扬顿挫,这里总结输入输出字符串。

③XmlFindCharEncodingHandler使用数据起初编码作为参数寻找libxml已经做到的调换器句柄并将找到的函数指针再次回到,若无找到则赶回NULL。

④The conversion function identified by handler requires as its arguments

pointers to the input and output strings, along with the length of each.
The

lengths must be determined separately by the application.

由句柄内定的转变函数央求输入、输出字符中及它们的长度作为参数。这一个长度必得由应用程序分别钦定。

⑤用内定编码并不是UTF-8输出,我们采用xmlSaveFormatFileEnc指不定时编码方式。 

 

A. 编译

Libxml包罗一个脚本xml2-config,它日常用来编写翻译和链接程序到库时产生标记。为了获取预管理和编写翻译标记,使用xml2-config
–cflags
,为了获得链接标识,使用xml2-config
–libs。
任何有效的参数请使用xml2-config –help查阅。

 

B. 示例文档

<?xml version=”1.0″?>

<story>

<storyinfo>

<author>John Fleck</author>

<datewritten>June 2, 2002</datewritten>

<keyword>example keyword</keyword>

</storyinfo>

<body>

<headline>This is the headline</headline>

<para>This is the body text.</para>

</body>

</story>

C. Keyword例程代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <libxml/xmlmemory.h>

#include <libxml/parser.h>

void

parseStory (xmlDocPtr doc, xmlNodePtr cur) {

xmlChar *key;

cur = cur->xmlChildrenNode;

while (cur != NULL) {

if ((!xmlStrcmp(cur->name, (const xmlChar *)”keyword”))) {

key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);

printf(“keyword: %s/n”, key);

xmlFree(key);

}

cur = cur->next;

}

return;

}

static void

parseDoc(char *docname) {

xmlDocPtr doc;

xmlNodePtr cur;

doc = xmlParseFile(docname);

if (doc == NULL ) {

fprintf(stderr,”Document not parsed successfully. /n”);

return; 

}

cur = xmlDocGetRootElement(doc);

if (cur == NULL) {

fprintf(stderr,”empty document/n”);

xmlFreeDoc(doc);

return;

}

if (xmlStrcmp(cur->name, (const xmlChar *) “story”)) {

fprintf(stderr,”document of the wrong type, root node != story”);

xmlFreeDoc(doc);

return;

}

cur = cur->xmlChildrenNode;

while (cur != NULL) {

if ((!xmlStrcmp(cur->name, (const xmlChar *)”storyinfo”))){

parseStory (doc, cur);

}

cur = cur->next;

}

xmlFreeDoc(doc);

return;

}

int

main(int argc, char **argv) {

char *docname;

if (argc <= 1) {

printf(“Usage: %s docname/n”, argv[0]);

return(0);

}

docname = argv[1];

parseDoc (docname);

return (1);

}

D. XPath例程代码

#include <libxml/parser.h>

#include <libxml/xpath.h>

xmlDocPtr

getdoc (char *docname) {

xmlDocPtr doc;

doc = xmlParseFile(docname);

if (doc == NULL ) {

fprintf(stderr,”Document not parsed successfully. /n”);

return NULL;

 

return doc;

}

xmlXPathObjectPtr

getnodeset (xmlDocPtr doc, xmlChar *xpath){

xmlXPathContextPtr context;

xmlXPathObjectPtr result;

context = xmlXPathNewContext(doc);

result = xmlXPathEvalExpression(xpath, context);

if(xmlXPathNodeSetIsEmpty(result->nodesetval)){

printf(“No result/n”);

return NULL;

}

xmlXPathFreeContext(context);

return result;

}

int

main(int argc, char **argv) {

char *docname;

xmlDocPtr doc;

xmlChar *xpath = (“//keyword”);

xmlNodeSetPtr nodeset;

xmlXPathObjectPtr result;

int i;

xmlChar *keyword;

if (argc <= 1) {

printf(“Usage: %s docname/n”, argv[0]);

return(0);

}

docname = argv[1];

doc = getdoc(docname);

result = getnodeset (doc, xpath);

if (result) {

nodeset = result->nodesetval;

for (i=0; i < nodeset->nodeNr; i++) {

keyword = xmlNodeListGetString(doc,
nodeset->nodeTab[i]->printf(“keyword: %s/n”, keyword);

xmlFree(keyword);

}

xmlXPathFreeObject (result);

}

xmlFreeDoc(doc);

xmlCleanupParser();

return (1);

}

E. 增加keyword例程代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <libxml/xmlmemory.h>

#include <libxml/parser.h> 

 

void

parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {

xmlNewTextChild (cur, NULL, “keyword”, keyword);

return;

}

xmlDocPtr

parseDoc(char *docname, char *keyword) {

xmlDocPtr doc;

xmlNodePtr cur;

doc = xmlParseFile(docname);

if (doc == NULL ) {

fprintf(stderr,”Document not parsed successfully. /n”);

return (NULL);

}

cur = xmlDocGetRootElement(doc);

if (cur == NULL) {

fprintf(stderr,”empty document/n”);

xmlFreeDoc(doc);

return (NULL);

}

if (xmlStrcmp(cur->name, (const xmlChar *) “story”)) {

fprintf(stderr,”document of the wrong type, root node != story”);

xmlFreeDoc(doc);

return (NULL);

}

cur = cur->xmlChildrenNode;

while (cur != NULL) {

if ((!xmlStrcmp(cur->name, (const xmlChar *)”storyinfo”))){

parseStory (doc, cur, keyword);

}

cur = cur->next;

}

return(doc);

}

int

main(int argc, char **argv) {

char *docname;

char *keyword;

xmlDocPtr doc;

if (argc <= 2) {

printf(“Usage: %s docname, keyword/n”, argv[0]);

return(0);

}

docname = argv[1];

keyword = argv[2];

doc = parseDoc (docname, keyword);

if (doc != NULL) {

xmlSaveFormatFile (docname, doc, 0);

xmlFreeDoc(doc); 

}

return (1);

}

F. 增加属性例程代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <libxml/xmlmemory.h>

#include <libxml/parser.h>

xmlDocPtr

parseDoc(char *docname, char *uri) {

xmlDocPtr doc;

xmlNodePtr cur;

xmlNodePtr newnode;

xmlAttrPtr newattr;

doc = xmlParseFile(docname);

if (doc == NULL ) {

fprintf(stderr,”Document not parsed successfully. /n”);

return (NULL);

}

cur = xmlDocGetRootElement(doc);

if (cur == NULL) {

fprintf(stderr,”empty document/n”);

xmlFreeDoc(doc);

return (NULL);

}

if (xmlStrcmp(cur->name, (const xmlChar *) “story”)) {

fprintf(stderr,”document of the wrong type, root node != story”);

xmlFreeDoc(doc);

return (NULL);

}

newnode = xmlNewTextChild (cur, NULL, “reference”, NULL);

newattr = xmlNewProp (newnode, “uri”, uri);

return(doc);

}

int

main(int argc, char **argv) {

char *docname;

char *uri;

xmlDocPtr doc;

if (argc <= 2) {

printf(“Usage: %s docname, uri/n”, argv[0]);

return(0);

 

docname = argv[1];

uri = argv[2];

doc = parseDoc (docname, uri);

if (doc != NULL) {

xmlSaveFormatFile (docname, doc, 1);

xmlFreeDoc(doc);

}

return (1);

}

G. 得到属性值例程代码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <libxml/xmlmemory.h>

#include <libxml/parser.h>

void

getReference (xmlDocPtr doc, xmlNodePtr cur) {

xmlChar *uri;

cur = cur->xmlChildrenNode;

while (cur != NULL) {

if ((!xmlStrcmp(cur->name, (const xmlChar *)”reference”))) {

uri = xmlGetProp(cur, “uri”);

printf(“uri: %s/n”, uri);

xmlFree(uri);

}

cur = cur->next;

}

return;

}

void

parseDoc(char *docname) {

xmlDocPtr doc;

xmlNodePtr cur;

doc = xmlParseFile(docname);

if (doc == NULL ) {

fprintf(stderr,”Document not parsed successfully. /n”);

return;

}

cur = xmlDocGetRootElement(doc);

if (cur == NULL) {

fprintf(stderr,”empty document/n”);

xmlFreeDoc(doc);

return;

 

if (xmlStrcmp(cur->name, (const xmlChar *) “story”)) {

fprintf(stderr,”document of the wrong type, root node != story”);

xmlFreeDoc(doc);

return;

}

getReference (doc, cur);

xmlFreeDoc(doc);

return;

}

int

main(int argc, char **argv) {

char *docname;

if (argc <= 1) {

printf(“Usage: %s docname/n”, argv[0]);

return(0);

}

docname = argv[1];

parseDoc (docname);

return (1);

}

H. 编码调换例程代码

#include <string.h>

#include <libxml/parser.h>

unsigned char*

convert (unsigned char *in, char *encoding)

{

unsigned char *out;

int ret,size,out_size,temp;

xmlCharEncodingHandlerPtr handler;

size = (int)strlen(in)+1;

out_size = size*2-1;

out = malloc((size_t)out_size);

if (out) {

handler = xmlFindCharEncodingHandler(encoding);

if (!handler) {

free(out);

out = NULL;

}

}

if (out) {

temp=size-1;

ret = handler->input(out, &out_size, in, &temp);

if (ret || temp-size+1) {

if (ret) { 

 

printf(“conversion wasn’t successful./n”);

} else {

printf(“conversion wasn’t successful. converted: }

free(out);

out = NULL;

} else {

out = realloc(out,out_size+1);

out[out_size]=0; /*null terminating out*/

}

} else {

printf(“no mem/n”);

}

return (out);

}

int

main(int argc, char **argv) {

unsigned char *content, *out;

xmlDocPtr doc;

xmlNodePtr rootnode;

char *encoding = “ISO-8859-1”;

if (argc <= 1) {

printf(“Usage: %s content/n”, argv[0]);

return(0);

}

content = argv[1];

out = convert(content, encoding);

doc = xmlNewDoc (“1.0”);

rootnode = xmlNewDocNode(doc, NULL, (const xmlChar*)”root”, out);

xmlDocSetRootElement(doc, rootnode);

xmlSaveFormatFileEnc(“-“, doc, encoding, 1);

return (1);

}

I. 感谢

A number of people have generously offered feedback, code and suggested
improvements

to this tutorial. In no particular order: Daniel Veillard, Marcus Labib

Iskander, Christopher R. Harris, Igor Zlatkovic, Niraj Tolia, David
Turover

索引

A

attribute

retrieving value, 7

writing, 6

Libxml Tutorial

16

C

compiler flags, 9

E

element

retrieving content, 3

writing content, 6

encoding, 3, 7

F

file

parsing, 2-3

saving, 6

X

xmlChar, 2

xmlDoc, 2

xmlNodePtr, 2

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图