我需要通过 next_sibling 或 first_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]');
错误导航条件'/ * TON [@method]'()在C:/strawberry/perl/site/lib/XML/Twig.pm第3523行
答案 0 :(得分:3)
由于这不在XML :: Twig支持的XPath子集中,因此您必须使用自定义过滤器,方法是将代码传递给first_elt
:
$t->first_elt( sub { $_[0]->tag=~ m{TON$} && $_[0]->att( 'method') })
这将返回sub返回true值的第一个元素。
这种表达的需要有点令人不安。在您的示例中,您通过其名称以TON结尾的事实来定义一类元素。拥有CARLTON元素会发生什么?或者当需要使用SHERATON和HILTON处理MARRIOTT元素时?你需要重写你的查询吗?
如果您是设计数据格式的人,我建议您修改格式。 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') })
这样可以轻松添加/减少其他标签。
答案 1 :(得分:2)
使用强>:
*[substring(name(), string-length(name()) - 2) = 'TON'][@method][1]
<强>解释强>:
此表达式对XPath 2.0标准函数ends-with()
使用XPath 1.0 equevalent:
XPath 1.0等效的XPath 2.0表达式:
ends-with($s, $s2)
<强>是强>:
substring($s, string-lenth() - string-length($s2) + 1) = $s2
在最后一个表达式中,我们将$s
替换为name()
,将$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
属性。
第二个表达式从第一个表达式中选择第一个节点。