简体   繁体   English

使用 XML::Twig 更新包含命名空间前缀的 xml 文件

[英]Update xml file containing namespace prefix with XML::Twig

I have the following information in an xml file I need to amend:我需要修改的 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>

In general, the prefix "x:" can be anything, including the empty prefix.一般来说,前缀“x:”可以是任何东西,包括空前缀。

I now need to add a child element "x:sheet" to the "x:sheets" element in the file.我现在需要向文件中的“x:sheets”元素添加一个子元素“x:sheet”。 However, if the file contents had no prefixes then I would need to add a child element "sheet" to the "sheets" element in the file.但是,如果文件内容没有前缀,那么我需要在文件中的“sheets”元素中添加一个子元素“sheet”。

Since the prefix, in general, can be anything I use the following perl code to scan and amend the file.由于前缀,一般来说,可以是任何我使用下面的 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'});
}

For the case where the prefix is "x:" this code generates the desired result.对于前缀为“x:”的情况,此代码生成所需的结果。

However, in general, the prefix is unknown.但是,一般来说,前缀是未知的。 My handler maps the unknown prefix to the prefix "s:" So finding the correct element poses no problem.我的处理程序将未知前缀映射到前缀“s:”,因此找到正确的元素没有问题。

However, I cannot find any way of adding a new child element with the correct prefix.但是,我找不到任何添加具有正确前缀的新子元素的方法。

Is there any way I can get the original prefix from the file and use it when adding my new child element?有什么方法可以从文件中获取原始前缀并在添加新的子元素时使用它?

If you know the URI of the particular namespace you're interested in (In the variable $schema_uri in the below), you can look up the prefix (If any) being used in the document for it by iterating through all assigned prefixes looking for a match:如果您知道您感兴趣的特定命名空间的 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'});
}

This works with a prefix ( x:sheet ) and when it's the default namespace ( sheet ) in my testing.这适用于前缀 ( x:sheet ) 并且当它是我测试中的默认命名空间 ( sheet ) 时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM