首页 > 解决方案 > 如何使用 perl XML::LibXML 将多个 xml 文件解析为一个 DOM 对象?

问题描述

我想使用 perl 模块 XML::LibXML 将多个 xml 文件解析为一个 DOM 对象。

我有一个 xml 文件,其中包含要解析的其他 xml 文件的文件名。如果可能的话,我想在一个 DOM 对象中解析其他 xml 文件。我能够将所有 xml 文件一个一个地导入一个 DOM 对象。之前,我尝试使用模块 XML::Simple(不支持 DOM),并且可以轻松地合并来自多个 xml 文件的多个数组。不知道如何使用 DOM 做到这一点。xml 文件的确切内容与我的问题无关。

标签: xmlperldom

解决方案


使用 XInclude 指令可能会执行您所要求的操作。例如,这里有一个 XML 文档,它引用了另外两个 XML 文档,这个文档叫做libxml-xinclude.xml

<wrapper xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="libxml-xinclude-inc1.xml"/>
  <xi:include href="libxml-xinclude-inc2.xml"/>
</wrapper>

第一个引用的文档libxml-xinclude-inc1.xml看起来像这样:

<doc>
  <title>This is document one</title>
</doc>

第二个参考文档libxml-xinclude-inc2.xml看起来像这样:

<doc>
  <title>This is document two</title>
</doc>

XInclude 指令通常只被视为普通元素(带有命名空间),但您可以告诉一些 XML 解析器处理这些指令并将元素替换为引用文件的内容。下面是一个使用 XML::LibXML 的示例:

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

use XML::LibXML;

my $filename = 'libxml-xinclude.xml';

my $parser = XML::LibXML->new();

my $dom = $parser->load_xml(location => $filename);

$parser->process_xincludes( $dom );

say $dom->toString();

这将产生这个输出:

<?xml version="1.0"?>
<wrapper xmlns:xi="http://www.w3.org/2001/XInclude">
  <doc>
  <title>This is document one</title>
</doc>
  <doc>
  <title>This is document two</title>
</doc>
</wrapper>

请注意,最终文档包括<wrapper>来自原始来源的元素以及来自引用文档的所有包含的元素。您现在可以使用XPath 表达式提取您感兴趣的位。

使用 XInclude 存在潜在的安全隐患。该href属性可以是一个 URL,因此它可能会从运行代码的主机发出 HTTP 请求,或者从系统中提取任意文件(例如:href="/etc/passwd")。因此,您几乎肯定不想在面向 Internet 的 Web 应用程序的代码中使用它。


推荐阅读