使用 XML::Twig 更新包含命名空间前缀的 xml 文件
Update xml file containing namespace prefix with XML::Twig
我需要修改的 xml 文件中有以下信息:
<?xml version="1.0" encoding="utf-8"?>
<x:workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:workbookPr codeName="ThisWorkbook"/>
<x:bookViews>
<x:workbookView firstSheet="0" activeTab="0"/>
</x:bookViews>
<x:sheets>
<x:sheet name="Sheet1" sheetId="2" r:id="rId2"/>
</x:sheets>
<x:definedNames/>
<x:calcPr calcId="125725"/>
</x:workbook>
一般来说,前缀“x:”可以是任何内容,包括空前缀。
我现在需要将子元素“x:sheet”添加到文件中的“x:sheets”元素。
但是,如果文件内容没有前缀,那么我需要将子元素“sheet”添加到文件中的“sheets”元素。
因为前缀,一般来说,可以是任何东西我用下面的perl代码来扫描和修改文件。
use strict;
use warnings;
use XML::Twig;
my $fileName1='/folder1/file1.xml';
my $fh1;
my $fh1_filename='/folder1/file1_NEW.xml';
my $tw1=new XML::Twig(
map_xmlns => {
'http://schemas.openxmlformats.org/officeDocument/2006/relationships' => 'r',
'http://schemas.openxmlformats.org/spreadsheetml/2006/main' => 's'
},
keep_original_prefix => 1,
pretty_print => 'indented',
twig_handlers => {'/s:workbook/s:sheets' => sub{Add_Sheet_1(@_)}}
);
$tw1->parsefile($fileName1);
open($fh1, '>:encoding(UTF-8)', $fh1_filename);
$tw1->flush($fh1);
close $fh1;
}
#
#
#
sub Add_Sheet_1{
my ( $twig, $tag) = @_;
my $var1='x:sheet';
$tag->insert_new_elt( 'last_child', => $var1=>{name=>'Sheet_N1',sheetId=>'200'});
}
对于前缀为“x:”的情况,此代码生成所需的结果。
但是,一般来说,前缀是未知的。我的处理程序将未知前缀映射到前缀“s:”,因此找到正确的元素没有问题。
但是,我找不到任何方法来添加具有正确前缀的新子元素。
有什么方法可以从文件中获取原始前缀并在添加新子元素时使用它?
如果您知道您感兴趣的特定命名空间的 URI(在下面的变量 $schema_uri
中),您可以查找文档中使用的前缀(如果有)通过遍历所有分配的前缀寻找匹配项:
sub Add_Sheet_1{
my ($twig, $tag) = @_;
my $ns = "";
foreach my $prefix ($twig->parser->current_ns_prefixes) {
if ($twig->original_uri($prefix) eq $schema_uri) {
$ns = "$prefix:";
last;
}
}
my $name = $ns . "sheet";
$tag->insert_new_elt('last_child', $name, {name => 'Sheet_N1', sheetId => '200'});
}
这适用于前缀 (x:sheet
),并且在我的测试中它是默认命名空间 (sheet
)。
我需要修改的 xml 文件中有以下信息:
<?xml version="1.0" encoding="utf-8"?>
<x:workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:workbookPr codeName="ThisWorkbook"/>
<x:bookViews>
<x:workbookView firstSheet="0" activeTab="0"/>
</x:bookViews>
<x:sheets>
<x:sheet name="Sheet1" sheetId="2" r:id="rId2"/>
</x:sheets>
<x:definedNames/>
<x:calcPr calcId="125725"/>
</x:workbook>
一般来说,前缀“x:”可以是任何内容,包括空前缀。
我现在需要将子元素“x:sheet”添加到文件中的“x:sheets”元素。 但是,如果文件内容没有前缀,那么我需要将子元素“sheet”添加到文件中的“sheets”元素。
因为前缀,一般来说,可以是任何东西我用下面的perl代码来扫描和修改文件。
use strict;
use warnings;
use XML::Twig;
my $fileName1='/folder1/file1.xml';
my $fh1;
my $fh1_filename='/folder1/file1_NEW.xml';
my $tw1=new XML::Twig(
map_xmlns => {
'http://schemas.openxmlformats.org/officeDocument/2006/relationships' => 'r',
'http://schemas.openxmlformats.org/spreadsheetml/2006/main' => 's'
},
keep_original_prefix => 1,
pretty_print => 'indented',
twig_handlers => {'/s:workbook/s:sheets' => sub{Add_Sheet_1(@_)}}
);
$tw1->parsefile($fileName1);
open($fh1, '>:encoding(UTF-8)', $fh1_filename);
$tw1->flush($fh1);
close $fh1;
}
#
#
#
sub Add_Sheet_1{
my ( $twig, $tag) = @_;
my $var1='x:sheet';
$tag->insert_new_elt( 'last_child', => $var1=>{name=>'Sheet_N1',sheetId=>'200'});
}
对于前缀为“x:”的情况,此代码生成所需的结果。
但是,一般来说,前缀是未知的。我的处理程序将未知前缀映射到前缀“s:”,因此找到正确的元素没有问题。
但是,我找不到任何方法来添加具有正确前缀的新子元素。
有什么方法可以从文件中获取原始前缀并在添加新子元素时使用它?
如果您知道您感兴趣的特定命名空间的 URI(在下面的变量 $schema_uri
中),您可以查找文档中使用的前缀(如果有)通过遍历所有分配的前缀寻找匹配项:
sub Add_Sheet_1{
my ($twig, $tag) = @_;
my $ns = "";
foreach my $prefix ($twig->parser->current_ns_prefixes) {
if ($twig->original_uri($prefix) eq $schema_uri) {
$ns = "$prefix:";
last;
}
}
my $name = $ns . "sheet";
$tag->insert_new_elt('last_child', $name, {name => 'Sheet_N1', sheetId => '200'});
}
这适用于前缀 (x:sheet
),并且在我的测试中它是默认命名空间 (sheet
)。