2012-02-14 112 views
11

我解析XML时遇到问题。XML解析,TXMLDocument

如何获得字段值se_urlphrase
我需要link1_1link1_2key1link2_1link2_2key2 ... 这是在se_urlphrase

我没有在谷歌找到如何做到这一点(也没有找到如何与TXMLDocument工作手册)。

<doc> 
    <date2>20120214</date2> 
    <date1>20120214</date1> 
    <data count="116"> 
    <row> 
     <search_engines count="2"> 
     <search_engine> 
      <se_url>link1_1</se_url> 
      <se_page>1</se_page> 
      <se_id>2</se_id> 
     </search_engine> 
     <search_engine> 
      <se_url>link1_2</se_url> 
      <se_page>1</se_page> 
      <se_id>3</se_id> 
     </search_engine> 
     </search_engines> 
     <denial>0.4889</denial> 
     <visits>45</visits> 
     <page_views>52</page_views> 
     <phrase>key1</phrase> 
     <visit_time>126</visit_time> 
     <depth>1.1556</depth> 
    </row> 
    <row> 
     <search_engines count="2"> 
     <search_engine> 
      <se_url>link2_1</se_url> 
      <se_page>1</se_page> 
      <se_id>3</se_id> 
     </search_engine> 
     <search_engine> 
      <se_url>link2_2</se_url> 
      <se_page>1</se_page> 
      <se_id>6</se_id> 
     </search_engine> 
     </search_engines> 
     <denial>0.5714</denial> 
     <visits>42</visits> 
     <page_views>50</page_views> 
     <phrase>key2</phrase> 
     <visit_time>109</visit_time> 
     <depth>1.1905</depth> 
    </row> 
    </data> 
</doc> 
+1

对不起,我明白英文可能不是您的第一语言,因为文档托管在'.ru'域,但这个问题没有任何意义。你介意编辑它,并提供一些更具体的细节,特别是你要找的东西吗? – 2012-02-14 18:51:05

+4

将您的大部分问题发布到非现场链接意味着,如果该其他网站变得不可用或消失,它就变得毫无意义。请编辑您的问题,以便在此处提供至少部分XML文档,以便您的问题将来对其他人有用,并且可供搜索。在您编辑该部分时,您可以提供有关您目前尝试执行的操作以及尝试执行的操作的更多信息,并解释其未按预期工作的原因。谢谢。 :0 – 2012-02-14 19:10:49

+0

dredei我试图告诉你什么肯意味着,希望我的编辑帮助?你仍然应该扩大你的问题来说出你所尝试过的。你甚至尝试过使用MSXML DOM或OmniXML,或者你只是试图解析没有XML解析器? – 2012-02-14 22:01:48

回答

20

试试这个:

uses ComObj, MSXML; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    xml: IXMLDOMDocument; 
    node: IXMLDomNode; 
    nodes_row, nodes_se: IXMLDomNodeList; 
    i, j: Integer; 
    url: string; 
begin 
    // put url or file name 
    url := 'http://softez.pp.ua/gg.xml'; 

    xml := CreateOleObject('Microsoft.XMLDOM') as IXMLDOMDocument; 
    xml.async := False; 
    xml.load(url); // or use loadXML to load XML document using a supplied string 
    if xml.parseError.errorCode <> 0 then 
    raise Exception.Create('XML Load error:' + xml.parseError.reason); 

    Memo1.Clear; 
    nodes_row := xml.selectNodes('/doc/data/row'); 
    for i := 0 to nodes_row.length - 1 do 
    begin 
    node := nodes_row.item[i]; 
    Memo1.Lines.Add('phrase=' + node.selectSingleNode('phrase').text); 
    nodes_se := node.selectNodes('search_engines/search_engine/se_url'); 
    for j := 0 to nodes_se.length - 1 do 
    begin 
     node := nodes_se.item[j]; 
     Memo1.Lines.Add('url=' + node.text); 
    end; 
    Memo1.Lines.Add('--------------'); 
    end; 
end; 

结果:

phrase=key1 
url=link1_1 
url=link1_2 
-------------- 
phrase=key2 
url=link2_1 
url=link2_2 
-------------- 

参考,以IXMLDOMDocument

+2

+1。很好的答案。 :)耐心也很好。 (谢谢,顺便说一句)。 – 2012-02-15 14:19:16

+0

@KenWhite,谢谢*你*关心关于这些问题的质量:)(顺便说一句,你知道为什么我的代码没有着色?:/) – kobik 2012-02-15 14:23:55

+0

我不知道为什么它没有被语法突出显示。我去看了看源代码,看起来很好。我甚至增加了一个明确的语言评论,没有任何改变??? – 2012-02-15 14:53:16

4

如果先有这3个通用库例程....

uses XMLDoc, XMLIntf, xmldom; 

function CreateXMLDocument(var Owner1: TComponent): TXMLDocument; 
begin 
Owner1 := TComponent.Create(nil); 
result := TXMLDocument.Create(Owner1); 
result.Options := [doNodeAutoCreate, doNodeAutoIndent, doAttrNull, 
        doAutoPrefix, doNamespaceDecl]; 
result.DOMVendor := GetDOMVendor('MSXML'); 
end; 

function XPATHSelect(const FocusNode: IXMLNode; const sXPath: string): TArray<IXMLNode>; 
var 
    DomNodeSelect: IDomNodeSelect; 
    DOMNode  : IDomNode; 
    DocAccess : IXmlDocumentAccess; 
    Doc   : TXmlDocument; 
    DOMNodes  : IDOMNodeList; 
    iDOMNode  : integer; 
begin 
SetLength(result, 0); 
if assigned(FocusNode) and 
    Supports(FocusNode.DOMNode, IDomNodeSelect, DomNodeSelect) then 
    DOMNodes := DomNodeSelect.SelectNodes(sXPath); 
if not assigned(DOMNodes) then exit; 
SetLength(result, DOMNodes.Length); 
for iDOMNode := 0 to DOMNodes.Length - 1 do 
    begin 
    Doc := nil; 
    DOMNode := DOMNodes.item[iDOMNode]; 
    if Supports(DOMNode, IXmlDocumentAccess, DocAccess) then 
    Doc := DocAccess.DocumentObject; 
    result[ iDOMNode] := TXmlNode.Create(DOMNode, nil, Doc) as IXMLNode; 
    end 
end; 


function XPATHSelectFirst(const FocusNode: IXMLNode; const sXPath: string; var SelectedNode: IXMLNode): boolean; 
var 
    DomNodeSelect: IDomNodeSelect; 
    DOMNode  : IDomNode; 
    DocAccess : IXmlDocumentAccess; 
    Doc   : TXmlDocument; 
begin 
SelectedNode := nil; 
if assigned(FocusNode) and 
    Supports(FocusNode.DOMNode, IDomNodeSelect, DomNodeSelect) then 
    DOMNode := DomNodeSelect.selectNode(sXPath); 
if assigned(DOMNode) and 
    Supports(DOMNode.OwnerDocument, IXmlDocumentAccess, DocAccess) then 
    Doc := DocAccess.DocumentObject; 
if Assigned(DOMNode) then 
    SelectedNode := TXmlNode.Create(DOMNode, nil, Doc); 
result := assigned(SelectedNode) 
end; 

然后了一个非常巧妙的解决办法是...

procedure TForm2.btn1Click(Sender: TObject); 
const 
    DocumentSource = 'http://softez.pp.ua/gg.xml'; 
var 
    Doc: IXMLDocument; 
    DocOwner: TComponent; 
    RowNode, PhraseNode, UrlNode: IXMLNode; 

    procedure PutLn(const LineFmt: string; const Args: array of const); 
    begin 
    memo2.Lines.Add(Format(LineFmt, Args)) 
    end; 

begin 
memo2.Clear; 
Doc := CreateXMLDocument(DocOwner); 
Doc.LoadFromFile(DocumentSource); 
for RowNode in XPATHSelect(Doc.DocumentElement, '//row[phrase]') do 
    begin 
    if not XPATHSelectFirst(RowNode, 'phrase', PhraseNode) then continue; 
    PutLn('phrase=%s', [PhraseNode.NodeValue]); 
    for UrlNode in XPATHSelect(RowNode, 'search_engines/search_engine/se_url') do 
    PutLn('url=%s', [UrlNode.NodeValue]); 
    PutLn('--------------',[]) 
    end; 
DocOwner.Free; 
end; 

这是2010年德尔福测试和工程治疗。

4

和公正的良好措施,这里是另外一个答案,只要你不怕在一个小XSLT混!

const Transform = 
'<?xml version="1.0" encoding="utf-8"?>' + 
'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> ' + 
' <xsl:output method="text" indent="no"/>' + 
' <xsl:template match="text()|@*"/>' + 
' <xsl:template match="//row">' + 
' <xsl:text>phrase=</xsl:text>' + 
' <xsl:value-of select="phrase"/>' + 
' <xsl:text>&#10;</xsl:text>' + 
' <xsl:apply-templates/>' + 
' <xsl:text>--------------&#10;</xsl:text>' + 
' </xsl:template>' + 
' <xsl:template match="search_engines/search_engine/se_url">' + 
' <xsl:text>url=</xsl:text>' + 
' <xsl:value-of select="."/>' + 
' <xsl:text>&#10;</xsl:text>' + 
' </xsl:template>' + 
'</xsl:stylesheet>'; 


procedure TForm2.btn1Click(Sender: TObject); 
const 
    DocumentSource = 'http://softez.pp.ua/gg.xml'; 
var 
    Doc, Style: IXMLDocument; 
    DocOwner, StyleOwner: TComponent; 
    sOut: widestring; 
begin 
    memo2.Clear; 
    Doc := CreateXMLDocument(DocOwner); 
    Doc.LoadFromFile(DocumentSource); 
    Style := CreateXMLDocument(StyleOwner); 
    Style.LoadFromXML(Transform); 
    Doc.DocumentElement.TransformNode(Style.DocumentElement, sOut); 
    memo2.Lines.Add(sOut); 
    DocOwner.Free; 
    StyleOwner.Free 
end; 
+0

我似乎得到一个错误。它说“未声明的标识符:'CreateXMLDocument'”。我正在使用Delphi 10.1 Berlin Starter Edition和FireMonkey。然后我在与XML相关的使用列表中也有以下内容:Xml.xmldom,Xml.XMLIntf,Xml.adomxmldom,Xml.XMLDoc – 2017-02-10 10:17:19