2014-03-29 83 views
3

使用包含文字等號'myelement[@myatt =~ /test=/]'的XPath正則表達式將失敗,而使用十六進制代碼版本的等於將傳遞:'myelement[@myatt =~ /test\x3c/]'。至於爲什麼會出現這種情況,我在XML::Twig中找不到任何文檔。XML :: Twig - xpath中的正則表達式失敗,等號=

設置

我用的XPath使用正則表達式爲XML::Twig處理器練習。我最近能夠在這個答案中成功地使用帶有邊界條件的正則表達式:Updating xml attribute value based on other with Perl,所以我決定通過攻擊這個問題來看看樹枝是否可以處理兩個正則表達式條件:Best way to match Attribute value in XML element

use strict; 
use warnings; 

use XML::Twig; 

my $data = do { local $/; <DATA> }; 

my $t= XML::Twig->new( 
    twig_handlers => { 
     q{measValue[@dn =~ /Host=/]} => sub { print "(with =) $_->{att}{name}\n" }, 
     q{measValue[@dn =~ /Host/]} => sub { print "(w/o =) $_->{att}{name}\n" }, 
    }, 
    pretty_print => 'indented', 
); 
$t->parse($data); 

__DATA__ 
<root> 
    <measValue dn="Cabinet=0, Shelf=0, Card=2, Host=2" name="host != 0"> 
     <r p="1">not it</r> 
     <r p="2">not it</r> 
    </measValue> 
    <measValue dn="Cabinet=0, Shelf=0, Card=2, Host=0" name="good record"> 
     <r p="1">1.42</r> 
     <r p="2">2.28</r> 
    </measValue> 
    <measValue dn="Cabinet=0, Shelf=0, Card=22, Host=0" name="card != 2"> 
     <r p="1">not it</r> 
     <r p="2">not it</r> 
    </measValue> 
</root> 

輸出缺少「與=」:

(w/o =) host != 0 
(w/o =) good record 
(w/o =) card != 2 

不幸的是,我想,當一個XPath的正則表達式中使用普通等號=如下面的腳本演示撞上了路障

正如您所看到的,在正則表達式中包含文字等號會導致它們全部失敗。然後我試着用黑色\=逃跑,這沒有幫助。之後,我嘗試使用匹配的十六進制代碼\x3c

q{measValue[@dn =~ /Host\x3d/]} => sub { print "(with \\x3d) $_->{att}{name}\n" }, 
    q{measValue[@dn =~ /Host\=/]} => sub { print "(with \\=) $_->{att}{name}\n" }, 

輸出:

(with \x3d) host != 0 
(with \x3d) good record 
(with \x3d) card != 2 

這使我的最終工作的解決方案:

q{measValue[@dn =~ /Host\x3d0\b/ and @dn =~ /Card\x3d2\b/]} => sub { print "(full match) $_->{att}{name}\n" }, 

輸出:

(full match) good record 

系統規格

>perl -v 
This is perl 5, version 16, subversion 2 (v5.16.2) built for MSWin32-x64-multi-thread 

>cpan -D XML::Twig 
Installed: 3.46 
CPAN:  3.46 up to date 

問題

我的問題是,我可以找到爲什麼等號=不包括在XML::Twig XPath的正則表達式時,也沒有匹配的文件爲什麼會需要這樣的落後方式逃避它。此外,還有哪些其他意想不到的正則表現行爲?

我沒有問題繼續推薦這個模塊。但是,我建議人們在處理程序中執行它們的正則表達式過濾,而不是xpath,除非有人可以推薦一些好的文檔和預測行爲的方法。

+0

@downvoter反饋歡迎如果問題不清楚或可以改進。 – Miller

+0

它看起來像一個bug。我會在這個週末看看它 – mirod

+0

^XML :: Twig的作者 – ikegami

回答

4

確實這是一個錯誤。它在XML :: Twig 3.47中得到修復,它正在向您附近的CPAN鏡像發送。它也可在http://xmltwig.org/xmltwig/

「XPath解析器」並不是真正的解析器,它主要是煙霧和鏡像,使用正則表達式將XPath表達式轉換爲在解析過程中運行的Perl片段。在這種情況下,正則表達式幾乎被忽略,除了=符號以外,它被eq代替,因爲它遵循了一個看起來像XML名稱(「主機」)的東西,並且後面沒有數字。哎呀!正則表達式現在可以被正確識別並保留。

感謝您的錯誤報告。

3

正如@mirod所解釋的,「是的,這是一個錯誤。XPath解析器變得困惑,認爲=是一個測試,所以它在正則表達式中用eq代替它。」

這是通過下面的流線型例證實:

use strict; 
use warnings; 

use XML::Twig; 

my $data = do { local $/; <DATA> }; 

my $t= XML::Twig->new( 
    twig_handlers => { 
     q{myelement[@myatt =~ /val=/]} => sub { print "/val=/  matches '$_->{att}{myatt}'\n" }, 
     q{myelement[@myatt =~ /val\x3d/]} => sub { print "/val\\x3d/ matches '$_->{att}{myatt}'\n" }, 
    }, 
); 
$t->parse($data); 

__DATA__ 
<root> 
    <myelement myatt="val eq "/> 
    <myelement myatt="val="/> 
</root> 

輸出:

/val=/  matches 'val eq ' 
/val\x3d/ matches 'val=' 

報道在CPAN:#94295: XPath regex translates literal '=' to ' eq '

由於Mirod。