2012-02-14 16 views
11

У меня проблема с разбором XML.XML-синтаксический анализ, TXMLDocument

Как получить значения поля se_url и phrase?
мне нужно получить link1_1, link1_2, key1, link2_1, link2_2, key2 ... , которые находятся в se_url и phrase.

Я не нашел в Google, как это сделать (также не нашел руководства по работе с 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, но этот вопрос не имеет никакого смысла. Не могли бы вы отредактировать его и немного подробнее узнать о том, что именно вы ищете? –

+4

Проводка большей части вашего вопроса в ссылке за пределы сайта означает, что становится бессмысленным, если этот другой сайт становится недоступным или уходит. Измените свой вопрос, чтобы предоставить здесь хотя бы часть XML-документа, чтобы ваш вопрос оставался полезным для других в будущем и доступен для поиска. Пока вы редактируете эту часть, вы можете предоставить дополнительную информацию о том, что вы пытаетесь сделать и что вы пробовали, и объяснить, как она не работает должным образом. Благодарю. : 0 –

+0

dredei Я пытался показать вам, что означает Кен, надеюсь, что мое редактирование поможет? Вы должны расширить свой вопрос, чтобы сказать, что вы пробовали. Вы даже пытались использовать MSXML DOM или OmniXML или просто пытались разобрать без синтаксического анализатора XML? –

ответ

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. Хороший ответ. :) Хорошее терпение тоже. (И спасибо, BTW.) –

+0

@KenWhite, Спасибо * вы * за заботу о качестве вопросов на SO :) (Кстати, вы знаете, почему мой код не раскрашен?: /) – kobik

+0

Я не знаю, почему он не выделяется синтаксисом. Я пошел и посмотрел на источник, и все выглядит хорошо.Я даже добавил явный комментарий к языку без изменений. ??? –

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; 

Это был протестирован на Delphi 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 –

Смежные вопросы