Rya*_*ubi 6 xml perl xpath dom
看过使用XML/XPath的各种流行模块后,我还没有看到实现这一目标的直接方法.
从本质上讲,界面看起来像:
my $xpath = get_path($node1, $node2);
Run Code Online (Sandbox Code Playgroud)
...它将返回从$ node1到$ node2的相对路径.
我将自己的时间用于计算"效率" - 我将采用任何现有的解决方案来解决这个问题.如果不这样做,我想知道在任何"明显的"本土解决方案中可能遇到的一些陷阱.
在我的脑海中,我可以想象只是首先在$ node1的后代中搜索$ node2,然后失败,迭代$ node1的祖先做同样的事情.这会像我担心的那样是资源密集型的吗?
对于我的特定用例,我可以假设$ node1和$ node2的绝对路径都是已知的.考虑到这一点,我想认为可以在两个完整路径之间完成一些"XPath数学",而不必遍布整个树,但我不知道那个过程会是什么样子.
总结一下:
1)现有的CPAN模块是否能让我想做的事情变得简单?
2)如果没有,那么有效的方法是什么?
找到两个节点的绝对路径.
ref: root foo bar[2] baz[1] moo
target: root foo bar[2] baz[2] moo
Run Code Online (Sandbox Code Playgroud)
删除常见的领导段.
ref: baz[1] moo
target: baz[2] moo
Run Code Online (Sandbox Code Playgroud)
对于引用中的每个段,在目标前添加一个..段.
.. .. baz[2] moo
Run Code Online (Sandbox Code Playgroud)
转换为XPath.
../../baz[2]/moo
Run Code Online (Sandbox Code Playgroud)
码:
use XML::LibXML qw( XML_ATTRIBUTE_NODE XML_ELEMENT_NODE );
sub get_path_segs {
my ($node) = @_;
my @path = split(/\//, $node->nodePath());
shift(@path);
return @path;
}
sub get_path {
my ($ref, $targ) = @_;
die if $ref->nodeType() != XML_ELEMENT_NODE && $ref->nodeType() != XML_ATTRIBUTE_NODE;
die if $targ->nodeType() != XML_ELEMENT_NODE && $targ->nodeType() != XML_ATTRIBUTE_NODE;
my @ref = get_path_segs($ref);
my @targ = get_path_segs($targ);
while (@ref && @targ && $ref[0] eq $targ[0]) {
shift(@ref);
shift(@targ);
}
while (@ref) {
pop(@ref);
unshift(@targ, '..');
}
return @targ ? join('/', @targ) : '.';
}
Run Code Online (Sandbox Code Playgroud)
它目前支持元素和属性节点.它可以扩展为支持其他节点类型,可能是平凡的.
| 归档时间: |
|
| 查看次数: |
1546 次 |
| 最近记录: |