【问题标题】:XML parsing, TXMLDocumentXML解析,TXMLDocument
【发布时间】:2012-03-06 03:28:15
【问题描述】:

我在解析 XML 时遇到问题。

如何获取字段值se_urlphrase
我需要得到link1_1link1_2key1link2_1link2_2key2... 在se_urlphrase 中。

我在 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>

【问题讨论】:

  • 对不起,我知道英语可能不是您的第一语言,因为该文档托管在 .ru 域上,但这个问题没有任何意义。您介意对其进行编辑并提供更多详细信息来具体说明您要查找的内容吗?
  • 将您的大部分问题发布在非现场链接中意味着如果该其他网站不可用或消失,它将变得毫无意义。请编辑您的问题以在此处提供至少部分 XML 文档,以便您的问题在未来对其他人有用并且可以搜索。在您编辑该部分时,您可以提供有关您正在尝试做什么以及到目前为止您已经尝试过什么的更多信息,并解释它如何没有按预期工作。谢谢。 :0
  • dredei 我试图向您展示 Ken 的意思,希望我的编辑有所帮助?您仍然应该扩展您的问题以说出您尝试过的内容。您是否尝试过 MSXML DOM 或 OmniXML,或者您只是尝试在没有 XML 解析器的情况下进行解析?
  • @Warren,您刚刚取消了发帖人回来编辑问题的所有动机。 (你所做的与完成某人的整个家庭作业一样,然后告诉他们应该在之后阅读这本书。)
  • 更新了第一篇文章并更改了链接:)

标签: xml delphi xml-parsing txmldocument


【解决方案1】:

试试这个:

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的引用

【讨论】:

  • @KenWhite,感谢关心关于 SO 问题的质量 :) (顺便说一句,你知道为什么我的代码没有着色吗?:/)跨度>
  • 我不知道为什么它没有被语法高亮。我去看看源码,看起来还不错。我什至添加了一个明确的语言注释,没有任何变化。 ???
  • 还有一个问题:如何获取属性值?
  • node.attributes.getNamedItem('count').text.
【解决方案2】:

如果您首先包含这 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 上测试的,效果很好。

【讨论】:

    【解决方案3】:

    为了更好地衡量,这里是另一个答案,前提是您不怕混入一点 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;
    

    【讨论】:

    • 我似乎遇到了错误。它说“未声明的标识符:'CreateXMLDocument'”。我正在使用 Delphi 10.1 Berlin Starter Edition 和 FireMonkey。然后我的使用列表中也有以下与 XML 相关的内容:Xml.xmldom、Xml.XMLIntf、Xml.adomxmldom、Xml.XMLDoc
    猜你喜欢
    • 2017-07-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 2012-05-21
    • 2012-02-12
    • 2010-09-10
    • 2011-06-25
    • 2019-04-29
    相关资源
    最近更新 更多