2012-02-14 19 views
11

Tengo un problema con el análisis de XML.XML de análisis, TXMLDocument

¿Cómo obtener los valores de campo se_url y phrase?
Necesito conseguir link1_1, link1_2, key1, link2_1, link2_2, key2 ... que están en se_url y phrase.

No encontré en Google cómo hacerlo (tampoco encontré un manual sobre cómo trabajar con 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

Lo siento, entiendo que el inglés probablemente no es su primer idioma, ya que el documento está alojado en un dominio '.ru', pero esta pregunta no tiene ningún sentido. ¿Te importaría editarlo y proporcionar un poco más de detalle en cuanto a lo que estás buscando específicamente? –

+4

Publicar la mayor parte de su pregunta en un enlace externo significa que no tiene sentido si ese otro sitio deja de estar disponible o se va. Edite su pregunta para proporcionar al menos parte del documento XML aquí, para que su pregunta siga siendo útil para otros en el futuro y pueda buscarse. Mientras edita esa parte, puede proporcionar más información sobre lo que intenta hacer y lo que ha intentado hasta ahora, y explicarle cómo no funcionó como se esperaba. Gracias. : 0 –

+0

dredei Traté de mostrarle lo que Ken quiere decir, espero que mi edición ayude? Deberías expandir tu pregunta para decir lo que has intentado. ¿Intentó MSXML DOM u OmniXML o simplemente intentó analizar sin un analizador XML? –

Respuesta

20

Prueba esto:

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; 

Resultado:

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

una referencia a IXMLDOMDocument

+2

+1. Buena respuesta. :) Buena paciencia, también. (Y gracias, BTW.) –

+0

@KenWhite, gracias * por * preocuparse por la calidad de las preguntas en SO :) (Por cierto, ¿sabes por qué mi código no está coloreado?: /) – kobik

+0

No sé por qué no está siendo resaltado por sintaxis. Fui y miré la fuente, y se ve bien.Incluso agregué un comentario de lenguaje explícito sin cambios. ??? –

4

Si se incluye por primera vez estos 3 rutinas generales de la biblioteca propósito ....

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; 

entonces una solución más limpia es mucho ...

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; 

Esto fue probado en Delphi 2010 y trabaja un convite.

4

Y esta es otra respuesta, siempre que no tenga miedo de mezclar un poco de 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

Parece que estoy recibiendo un error. Dice "Identificador no declarado: 'CreateXMLDocument'". Estoy usando Delphi 10.1 Berlin Starter Edition y FireMonkey. Luego, también tengo lo siguiente en mi lista de usos que está relacionado con XML: Xml.xmldom, Xml.XMLIntf, Xml.adomxmldom, Xml.XMLDoc –