1

我需要找到特定的名称(即,一些匹配几个正则表达式的名称)并为每个隐藏它们对应的值,无论它们出现在 xml 中的任何位置 通过使用 XML 解析库(Twig?libXML?其他?)
regexp 部分不适用于parsing,但是然后选择我需要编辑的节点(即,我需要使用 XML 感知库进行解析,但只替换名称与特定复杂正则表达式匹配的节点中的值)。

对没有提供代码尝试深表歉意:(尽管我确实尝试调整了一些答案(例如:https ://stackoverflow.com/a/11482566/1841533 ,还有很多其他的)我太陌生了Perl 想出了一些东西,1) 可以浏览文件中的任何深度,2) 寻找与正则表达式匹配的名称。发布我微薄的尝试只会“缩小”讨论的方向(即,我真的想避免XYProblem:如果我展示了我现有的尝试,并且它们已得到纠正,则以下要求将不匹配,因为我的尝试也缺乏“在任何深度”或“与正则表达式匹配的名称”完全......)

**如果您需要(我完全可以理解...)示例代码,请不要进一步阅读。**(或者只是一点点,看看我为什么不提供任何内容)
如果您可以阅读下面的 3 个 XML 示例,以及以下 4 个点,指示我需要对它们做什么,(或者更好,之后的所有内容'我需要什么:' 行),并为我提供一个“模板”脚本(即,一些 perl,如果可能的话使用 twig 或 libXML),我将永远欠你的债^^。
[我确实花了很多时间在各种 se 网站上为许多人提供帮助......我经常希望他们发布示例代码。所以我理解为什么很多人会对此投反对票,或者只是不回答,或者感到沮丧。但是如果不“扭曲”我需要太多的东西,我就无法在这里生成一个示例代码,从而创建一个 XY 问题,而不是我尝试的...]

我需要的

我有许多具有不同结构的 xml 文件。

在以下内容中:“someNames”可能是几个不同的字符串,其中我只需要找到与(复杂)正则表达式匹配的字符串。
一旦我找到一个(或多个匹配)“someValue”将是关联的值,我想用通用字符串替换它。

xmls 非常简单,但它们仍然有几种不同的结构:

例如,有时 XML 可能包含

...
   <sometag  name=someName  value=someValue>  
...

(someName 或 someValue 可以在引号内或不在引号内)

或者

...
   <someName>someValue</someName>  
...

甚至另一种形式:

... 
   <someothertag   someName=someValue>
...
  • someValue 在“=”之后可以带引号,也可以不带引号,具体取决于 xml
  • someName 也可以在引号内或不在引号内,当它写成时name=someName
  • 每个文件中的 someName 更改,但我想找到一些匹配特定复杂正则表达式(例如: /\(abc\)|\([^xyz]*def\)|..../,即正则表达式可能非常复杂)

  • 对于那些匹配正则表达式的“someName”,并且只有它们匹配,我想通过通用字符串更改相应的“someValue”,例如“hidden”。(someValue 本身可以在每个文件中更改。但无论它是什么(即可以匹配“.*”),我想用新值“隐藏”替换它)

标签的深度也可能因文件而异(因此我需要通用解析)

很抱歉,但我找不到如何做到这一点,因为我在这里找到的每个示例都是针对特定标签或特定结构的,从它们中我无法掌握使用方法twiglibXML做更通用的方法...... (我对 Perl 非常陌生!)

我很难找到如何放置正则表达式,甚至如何解析多个 XML 并在每个 xml 中的任何级别上查找名称

欢迎任何有关如何执行此操作的提示!

更新:我正在努力想出一个合理的第一次尝试......但我想当我想出一个时,我可以删除那个问题。现在我正在尝试 Grok https://stackoverflow.com/a/11482566/1841533:但这不是我需要的。我需要将该示例修改为 1)允许打开任何文件(而不是像该答案那样直接提供 XML) 2)我需要使用“findnodes”来查找其名称(tagName,而不是其对应)的任何标签匹配一个正则表达式(而不是一些固定的“字符串”)3)然后一旦我找到这些标记名,我需要编辑相应的值以将其更改为“隐藏”。

4

1 回答 1

2

XML::LibXML::XPathContext 的文档中有一个示例,用于查找名称与给定正则表达式匹配的所有节点

my $perlmatch = sub {
    die "Not a nodelist"
        unless $_[0]->isa('XML::LibXML::NodeList');
    die "Missing a regular expression"
        unless defined $_[1];

    my $nodelist = XML::LibXML::NodeList->new;
    my $i = 0;
    while(my $node = $_[0]->get_node($i)) {
        $nodelist->push($node) if $node->nodeName =~ $_[1];
        $i ++;
    }

    return $nodelist;
};

my $xc = XML::LibXML::XPathContext->new($node);
$xc->registerFunction('perlmatch', $perlmatch);
my @nodes = $xc->findnodes('perlmatch(//*, "foo|bar")');

该功能perlmatch允许您找到这样的节点:

<someName>someValue</someName>

函数中的关键行是:

$nodelist->push($node) if $node->nodeName =~ $_[1];

这需要一个XML::LibXML::Node并根据节点的名称评估给定的正则表达式。通过一些修改,您可以匹配属性的值name或在属性列表中搜索匹配项。我将把它作为练习留给读者,但是以下方法应该可以帮助您入门:

$node->attributes();
于 2013-11-11T20:15:48.793 回答