Perl XML::LibXML usage
我在使用XML :: LibXML时遇到了一些麻烦,我想知道是否有一种方法可以做我想做的事,或者是否应该更改我的XML。
此刻,我的XML如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <fftg> <rename> <mandatory>0</mandatory> <other_things_here /> </rename> <transfer> <mandatory>0</mandatory> <protocol>SFTP</protocol> <other_things_here /> </transfer> <transfer> <mandatory>1</mandatory> <protocol>FTP</protocol> <other_things_here /> </transfer> <mandatory>1</mandatory> <other_things_here /> </archive> <rename> <mandatory>1</mandatory> <other_things_here /> </rename> </actions> </fftg> |
如您所见,在"动作"下可以有不同类型的动作(一种或多种动作,每种动作下有不同的事物)
我想浏览每个动作并根据动作执行特定的操作。
我的问题是:由于存在多个相同类型的动作,因此脚本无法正常工作,并覆盖了相同类型的先前动作,或者特定动作的循环在相同类型的每个动作上重新循环
示例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | foreach my $transfer ($doc->findnodes('/fftg')) { # Browse Actions foreach my $action ($doc->findnodes('/fftg/actions/*')) { my $action_name = $action->nodeName(); my $actiontype = ucfirst($action->nodeName()); print"executing action $action_name ..\ "; # Browse action details foreach my $action_details ($doc->findnodes('/fftg/actions/'.$action_name)) { for my $detail ($action_details->findnodes('./*')) { print $detail->nodeName(),":", $detail->textContent(),"\ "; } } print"-------------\ "; } } |
结果1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | executing action rename .. mandatory: 0 other_things_here: mandatory: 1 other_things_here: ------------- executing action transfer .. mandatory: 0 protocol: SFTP other_things_here: mandatory: 1 protocol: FTP other_things_here: ------------- executing action transfer .. mandatory: 0 protocol: SFTP other_things_here: mandatory: 1 protocol: FTP other_things_here: ------------- executing action archive .. mandatory: 1 other_things_here: ------------- executing action rename .. mandatory: 0 other_things_here: mandatory: 1 other_things_here: ------------- |
如您所见,此结果是错误的,因为在每个"动作类型"(很好,已检测到)中,它都会在相同类型的每个动作上重新循环。
这是由于:
1 | foreach my $action_details ($doc->findnodes('/fftg/actions/'.$action_name)) { |
我该怎么做才能实现自己想要的目标? (如果可能的话,不更改XML)
我想要的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | executing action rename .. mandatory: 0 other_things_here: ------------- executing action transfer .. mandatory: 0 protocol: SFTP other_things_here: ------------- executing action transfer .. mandatory: 1 protocol: FTP other_things_here: ------------- executing action archive .. mandatory: 1 other_things_here: ------------- executing action rename .. mandatory: 1 other_things_here: ------------- |
谢谢
在旁注中,我想我可以更改XML并使用类似的方法来轻松修复它(但我不知道哪一个是这三个之间的最佳选择),但是我想避免下面这两个是因为XSD之后将很难生成(我想要每种操作类型都有特定的选项):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <fftg> <type>rename</type> <mandatory>0</mandatory> <other_things_here /> </action> <type>transfer</type> <mandatory>0</mandatory> <protocol>SFTP</protocol> <other_things_here /> <type>transfer</type> <mandatory>0</mandatory> <protocol>FTP</protocol> <other_things_here /> <type>archive</type> <mandatory>0</mandatory> <other_things_here /> <type>rename</type> <mandatory>0</mandatory> <other_things_here /> </actions> </fftg> |
或
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <fftg> <mandatory>0</mandatory> <other_things_here /> </action> <mandatory>0</mandatory> <protocol>SFTP</protocol> <other_things_here /> <mandatory>0</mandatory> <protocol>FTP</protocol> <other_things_here /> <mandatory>0</mandatory> <other_things_here /> <mandatory>0</mandatory> <other_things_here /> </actions> </fftg> |
再次感谢
问候,
首先,您在
1 | $doc->findnodes('/fftg/actions/rename') |
它的意思是"给我作为
此外,循环太多。第一个是多余的,因为可能只有一个根元素。应该有两个循环(一个在
1 2 3 4 5 6 7 8 | for my $action ($doc->findnodes('/fftg/actions/*')) { print"executing", $action->nodeName(),"\ "; for my $detail ($action->findnodes('./*')) { print $detail->nodeName(),":", $detail->textContent(),"\ "; } } |