给出一个定义了多个名称空间的XML文件,最简单的方法是使用XPath查询在DOM中搜索默认名称空间中的元素?
正如标题所示,这是使用Perl和libXML。
此外,可以在不对名称空间进行硬编码的情况下执行此操作(如果使用XPathContext定义名称空间,则可以查询文件的默认名称空间)
我要实现的目标:
我正在搜索许多不同年龄的xlsx电子表格文档,以查找某些公式并对其进行处理。
我希望只使用一个简单的findnodes(//f)
来收集每个工作表中的所有公式。
所有工作表都定义了多个名称空间,但是大多数元素似乎没有完全限定的名称空间。例如:
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
<sheetData>
<row r="1">
<c r="A1">
<f>SUM(1+2)</f>
<v>3</v>
</c>
<c r="A2">
<f>SUM(4+5)</f>
<v>9</v>
</c>
...
<controls>
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<mc:Choice Requires="x14">
<control shapeId="1" r:id="rId4" name="blah">
...
如上所述,我只关心公式,即:在上面的示例中,“ SUM(1 + 2)”和“ SUM(4 + 5)”。
如何仅提取这些数据?
该解决方案不必很漂亮,但必须始终有效(我不确定名称空间是否有太大变化。)
我可以通过grep / sed传递所有内容,但希望能够正确解析它不会太难...
答案 0 :(得分:3)
您可以使用local-name()
完全忽略名称空间:
...->findnodes('//*[local-name()="f"]')
请注意,通常来说,这不是最好的主意。例如,如果公式的语法取决于版本,并且您需要对其进行规范化,则可以在每个名称空间中分别搜索公式,然后根据名称空间运行不同的转换。
答案 1 :(得分:1)
没有 the 默认名称空间。标签之间的默认值可以不同。您实际上是在询问根元素的名称空间。您想要这样做以支持一些“足够相似”的格式,它的操作如下:
use XML::LibXML qw( );
use XML::LibXML::XPathContext qw( );
my $doc = XML::LibXML->new->parse_string($xml);
my $root_ns = $doc->documentElement->namespaceURI;
my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs( xl => $root_ns );
$xpc->findnodes('//xl:f', $doc)
但是您没有提出任何不使用已知名称空间的理由。您应该只使用以下内容:
use XML::LibXML qw( );
use XML::LibXML::XPathContext qw( );
my $doc = XML::LibXML->new->parse_string($xml);
my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs( xl => 'http://schemas.openxmlformats.org/spreadsheetml/2006/main' );
$xpc->findnodes('//xl:f', $doc)