2

我需要通过next_siblingfirst_elt选择下一个节点。但我想按节点名称过滤(包含字符串"TON"

first_elt ('HILTON[@method]' or 'SHERATON[@method]');

或者

next_sibling ('HILTON[@method]' or 'SHERATON[@method]');

或者

next_sibling ('TON[@method]');

我试过的例子(不工作):

#!/usr/bin/perl -w
use warnings;
use XML::Twig;
$t-> parsefile ('file.xml');

my $Y0=$t->first_elt('HILTON[@method]' or 'SHERATON[@method]');

它只会处理'HILTON [@method]'

my $Y0=$t->first_elt('/*TON[@method]');

C:/strawberry/perl/site/lib/XML/Twig.pm 第 3523 行的错误导航条件 '/*TON[@method]' ()

4

2 回答 2

3

由于这超出了 XML::Twig 支持的 XPath 子集,因此您必须使用自定义过滤器,将代码传递给first_elt

$t->first_elt( sub {  $_[0]->tag=~ m{TON$} && $_[0]->att( 'method') })

这将返回 sub 返回真值的第一个元素。

不过,对这种表达的需求有点令人不安。在您的示例中,您通过其名称以 TON 结尾的事实来定义一类元素。当你有一个 CARLTON 元素时会发生什么?或者当 MARRIOTT 元素需要与 SHERATON 和 HILTON 一起处理时?你需要重写你的查询吗?

如果您是设计数据格式的人,我建议您修改格式。HILTON 和 SHERATON 应该是 HOTEL、BRAND 或 OWNER 标签的属性。也许一个额外的属性会很有用,以标记这两种类型应该被类似地处理。只有当它是数据固有的属性时,此属性才有意义。

如果数据是这样的并且您对其格式没有输入,那么我将有一个标签列表来处理并检查这些:

my %TAGS_TO_PROCESS= map { $_ => 1 } qw( HILTON SHERATON);
my $elt= $t->first_elt( sub {  $TAGS_TO_PROCESS{$_[0]->tag} && $_[0]->att( 'method') })

这样添加/减去其他标签很容易。

于 2012-07-05T05:04:42.390 回答
2

使用

*[substring(name(), string-length(name()) - 2) = 'TON'][@method][1]

说明

此表达式对 XPath 2.0 标准函数使用 XPath 1.0 等效项ends-with()

XPath 2.0 表达式的 XPath 1.0 等效项:

ends-with($s, $s2)

substring($s, string-lenth() - string-length($s2) + 1) = $s2

在最后一个表达式中,我们$sname()$s2替换'TON'

基于 XSLT 的验证

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:copy-of select=
     "*[substring(name(), string-length(name()) - 2) = 'TON'][@method] "/>
==========  
     <xsl:copy-of select=
     "*[substring(name(), string-length(name()) - 2) = 'TON'][@method][1] "/>
 </xsl:template>
</xsl:stylesheet>

应用于此 XML 文档时:

<t>
 <HILTON method="buy"/>
 <TON method="burn"/>
 <TONIC method="drink"/>
 <HILTON nomethod="yes"/>
 <SHERATON/>
 <SHERATON method="visit"/>
</t>

转换计算两个 XPath 表达式,并将选定的节点复制到输出

<HILTON method="buy"/>
<TON method="burn"/>
<SHERATON method="visit"/>
==========  
     <HILTON method="buy"/>

第一个表达式选择所有元素 - 上下文节点的子节点,其名称以“TON”结尾并且也具有method属性。

第二个表达式从第一个表达式选择的节点中选择第一个节点。

于 2012-07-04T21:31:48.253 回答