【问题标题】:How does it work XPath in delphi?Delphi 中的 XPath 是如何工作的?
【发布时间】:2014-12-08 04:29:03
【问题描述】:

这是我的 xml 文件 (content.xml):

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head></head>
   <body>
      <h1>Lorem ipsum dolor sit amet</h1>
  </body>
</html>

这是我在 Delphi (XE5) 中的代码:

procedure TForm1.Button1Click(Sender: TObject);
var
 doc: IXMLDocument;
 Sel: IDOMNodeSelect;
 List : IDOMNodeList;
 query: String;
 begin
   content := TFile.ReadAllText('C:\temp\content.xml');
   doc := TXMLDocument.Create(Application);
   doc.LoadFromXML(content);
   doc.Active := True;
   query := '//descendant::html';
   Sel := doc.DOMDocument as IDomNodeSelect;
   List := Sel.selectNodes(query);
  // List.length is 0 !!!!
end;

为什么 List 为空的问题,应该包含四个元素:HTML、head、body、h1(即“html”标签及其所有子标签。根据http://www.w3schools.com/xpath/xpath_syntax.asp XPath 语法,我尝试了这些选项:

//html/* 
/html
/html/*

它们都不适合我,所以此时我不知道查询是否正常或我的代码在另一点失败。

【问题讨论】:

  • 肯定是重复的,因此我强烈怀疑这不会被否决/关闭。同时看看this
  • 嗨,感谢您的回答,我现在已经尝试过,但没有工作,首先我使用的是 IDomNode,我需要获取 IDOMNodeList,而且我希望查询有效,因为遵循 XPath 语法来自 W3S。
  • 嗨,笨蛋,我正在使用这个theroadtodelphi.wordpress.com/2013/05/29/…,你可以看到我的示例几乎相同,但仍然无法正常工作。

标签: delphi xpath


【解决方案1】:

您似乎在 Delphi 中使用 MSXML,因此您需要确保首先调用

doc.setProperty('SelectionLanguage', 'XPath')

然后设置

doc.setProperty('SelectionNamespaces', 'xmlns:xhtml="http://www.w3.org/1999/xhtml"')

最后你需要在任何你想要限定元素的地方使用前缀xhtml,例如

doc.selectNodes('//xhtml:h1')

选择所有h1 元素。

【讨论】:

  • 感谢您的回答,但我没有使用 MSXML。 “doc”变量属于 Xml.XMLIntf 库。
  • @user3779155:仅供参考 - XMLIntf 是 Windows 下 MSXML 的包装器
【解决方案2】:

我建议不要在这种情况下使用TFile.ReadAllText()。让TXMLDocument直接加载文件,就不用处理任何编码问题了。

您可以去掉 doc.LoadFromXML() 并改为设置 doc.FileName 属性:

procedure TForm1.Button1Click(Sender: TObject);
var
  doc: TXMLDocument;
  ...
begin
  doc := TXMLDocument.Create(Application);
  try
    doc.FileName := 'C:\temp\content.xml';
    doc.Active := True;
    ...
  finally
    doc.Free;
  end;
end;

或者您可以将TXMLDocument 替换为LoadXMLDocument() 函数,该函数将文件名作为输入:

procedure TForm1.Button1Click(Sender: TObject);
var
  doc: IXMLDocument;
  ...
begin
  doc := LoadXMLDocument('C:\temp\content.xml');
  ...
end;

无论哪种方式,您都可以按照 Martin Honnen 的建议处理 XPath 查询。

【讨论】:

  • Remy 为什么在第一个示例中使用 TXMLDocument?也应该是 IXMLDocument?
  • 理想情况下,是的。但我一直使用 OP 的示例,只要分配了 Owner,直接使用 TXMLDocument 是有效的。
  • 啊,错过了那个细节:)
【解决方案3】:

几小时后错误真的很简单,“内容”变量必须是 AnsiString 而不是字符串。 XPath 是对的,但变量不是。

错了

var
 content: String;// WRONG should be content: AnsiString;
 begin
  content := TFile.ReadAllText('C:\temp\content.xml');
  doc := TXMLDocument.Create(Application);
  doc.LoadFromXML(content);
  doc.Active := True;

 end;

我看错地方了:查询变量和 XPath 语法。

【讨论】:

  • List.length is 0 !!!! 和以前一样,我不明白这怎么可能是答案,主要问题是没有处理命名空间。问题中甚至没有显示内容声明。
  • 我建议不要在这种情况下使用TFile.ReadAllText()。让TXMLDocument 直接加载文件。去掉 doc.LoadFromXML() 并设置 doc.FileName 属性,或者将 TXMLDocument 组件替换为 LoadXMLDocument() 函数,该函数将文件名作为输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
相关资源
最近更新 更多