草庐IT

带有 text() 和 SimpleXMLElement->xpath 的 php xpath 不符合 xpath 预期结果

coder 2024-04-16 原文

我正在尝试获取/td/span 的所有文本节点。

我正在尝试使用 xpath/td/span/text()

问题是它返回每个文本元素的所有文本节点(这里有两个,“193”和“120”,它返回两次“193120”,而不是在单独的元素中返回 193 和 120)。

我在任何在线工具上尝试了完全相同的 xpath,它工作正常,在 php 中,结果完全不同。

使用 SimpleXMLElement

$xhtmlSnippet = '<td><span>193<span>10</span><span></span><div>66</div><span>195</span><span>.</span><span>34</span><span>242</span><span></span>120<span>64</span></span></td>';

$xml = new SimpleXMLElement($xhtmlSnippet);

$xresult = $xml->xpath('/td/span/text()');    

foreach($xresult as $xnode){
    echo "<br /><br />NodeValue: " . $xnode;
}

给我:

NodeValue: 193120

NodeValue: 193120

这是它通过在线工具正常工作的示例(所有其他在线工具也提供预期的输出):

Working example in online tester

编辑:

使用 DOMDocument + DOMXPath,它似​​乎按预期工作:

    $dom = new DOMDocument;
    $dom->loadXML($xhtmlSnippet);

    $xpath = new DOMXPath($dom);
    
    foreach ($xpath->query('/td/span/text()) as $textNode) {
        echo "\n\nTextNode: " . $textNode->nodeValue;
    }

给予:

TextNode: 193

TextNode: 120

最佳答案

SimpleXMLElement 只能表示元素和属性,可以单独表示,也可以表示相同类型的兄弟元素的集合。 ->xpath() method返回一个 SimpleXMLElement 对象数组,允许它们成为非兄弟节点,但不允许任何其他节点类型。

因此,表达式 /td/span/text()匹配两个文本节点,但将它们作为代表其父元素的对象返回,在本例中恰好是相同的 <span>元素,两次为您提供具有相同对象的数组。

难题的其余部分是,当您将 SimpleXML 元素转换为字符串时,它将所有直接后代文本和 CDATA 节点合并为一个字符串,因此 193120粘在一起。

因此输出为193120 , 两次。

(这绝对是不符合直觉的行为,尽管很难确切地知道 SimpleXML 在这种情况下应该做什么;如果 XPath 表达式解析为元素或属性以外​​的其他内容,也许产生错误会更好)。


由于 DOM API 具有可能存在于 XML 中的每种节点的对象,并且 PHP 包含该 API 的完整实现,因此 XPath 表达式将在那里按预期工作。更重要的是,SimpleXML 和 DOM 对象实际上都是相同内部内存结构的包装器,因此您可以使用 dom_import_simplexml() 编写将两者组合的操作。和 simplexml_import_dom() .

作为一个稍微不雅的示例,如果您想在您已经使用 SimpleXML 遍历过的元素的上下文中运行 XPath 表达式,您可以这样做:

$dom_node = dom_import_simplexml($simplexml_node);
$dom_xpath = new DOMXPath($dom_node->ownerDocument);
$dom_xpath_result = $dom_xpath->query('span/text()', $dom_node);

foreach($dom_xpath_result as $xnode){
    echo "<br /><br />NodeValue: " . $xnode->nodeValue;
}

显然,您可以根据需要将其包装到一个函数中。另请注意,由于您的表达式从文档根目录(前导 /)开始,因此实际上下文无关紧要,这就是为什么我在上面使用了稍微不同的表达式。

关于带有 text() 和 SimpleXMLElement->xpath 的 php xpath 不符合 xpath 预期结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19847451/

有关带有 text() 和 SimpleXMLElement->xpath 的 php xpath 不符合 xpath 预期结果的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  3. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  4. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  5. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  6. ruby-on-rails - ruby 日期方程不返回预期的真值 - 2

    为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998

  7. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

    我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

  8. ruby-on-rails - 带有 Zeus 的 RSpec 3.1,我应该在 spec_helper 中要求 'rspec/rails' 吗? - 2

    使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做

  9. ruby-on-rails - 找不到 gem railties (>= 0.a) (Gem::GemNotFoundException) - 2

    我已经看到了一些其他的问题,尝试了他们的建议,但没有一个对我有用。我已经使用Rails大约一年了,刚刚开始一个新的Rails项目,突然遇到了问题。我卸载并尝试重新安装所有Ruby和Rails。Ruby很好,但Rails不行。当我输入railss时,我得到了can'tfindgemrailties。我当前的Ruby版本是ruby2.2.2p95(2015-04-13修订版50295)[x86_64-darwin15],尽管我一直在尝试通过rbenv设置ruby​​2.3.0。如果我尝试rails-v查看我正在运行的版本,我会得到同样的错误。我使用的是MacOSXElCapitan版本10

  10. Ruby:如何使用带有散列的 'send' 方法调用方法? - 2

    假设我有一个类A,里面有一些方法。假设stringmethodName是这些方法之一,我已经知道我想给它什么参数。它们在散列中{'param1'=>value1,'param2'=>value2}所以我有:params={'param1'=>value1,'param2'=>value2}a=A.new()a.send(methodName,value1,value2)#callmethodnamewithbothparams我希望能够通过传递我的哈希以某种方式调用该方法。这可能吗? 最佳答案 确保methodName是一个符号,而

随机推荐