gpt4 book ai didi

xml - 使用 XML::LibXML 删除 XML 命名空间

转载 作者:行者123 更新时间:2023-12-05 02:23:58 29 4
gpt4 key购买 nike

我正在将 XML 文档转换为 HTML。需要做的一件事是删除命名空间,它不能在 HTML 中合法声明(除非它是根标记中的 XHTML 命名空间)。我发现 5 到 10 年前的帖子说用 XML::LibXML 和 LibXML2 做这件事有多么困难,但最近没有那么多了。这是一个例子:

use XML::LibXML;
use XML::LibXML::XPathContext;
use feature 'say';

my $xml = <<'__EOI__';
<myDoc>
<par xmlns:bar="www.bar.com">
<bar:foo/>
</par>
</myDoc>
__EOI__

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

my $bar_foo = do{
my $xpc = XML::LibXML::XPathContext->new($doc);
$xpc->registerNs('bar', 'www.bar.com');
${ $xpc->findnodes('//bar:foo') }[0];
};
$bar_foo->setNodeName('foo');
$bar_foo->setNamespace('','');
say $bar_foo->nodeName; #prints 'bar:foo'. Dang!

my @namespaces = $doc->findnodes('//namespace::*');
for my $ns (@namespaces){
# $ns->delete; #can't find any such method for namespaces
}
say $doc->toStringHTML;

在这段代码中,我尝试了一些没有用的东西。首先,我尝试将 bar:foo 元素的名称设置为无前缀的 foo(文档说该方法知道 namespace ,但显然不是)。然后我尝试将元素命名空间设置为 null,但也没有用。最后,我通过文档查看了删除命名空间的方法。没有这样的运气。最终输出字符串仍然包含我想要删除的所有内容(命名空间声明和前缀)。

有没有人有办法删除命名空间,将元素和属性设置为空命名空间?

最佳答案

这是我自己的体操答案。如果没有更好的方法,那就行了。我当然希望有更好的方法...

replace_without_ns 方法只是复制没有命名空间的节点。相反,任何需要命名空间的子元素都会得到它们的声明。下面的代码将整个文档移动到 null 命名空间中:

use strict;
use warnings;
use XML::LibXML;

my $xml = <<'__EOI__';
<myDoc xmlns="foo">
<par xmlns:bar="www.bar.com" foo="bar">
<bar:foo stuff="junk">
<baz bar:thing="stuff"/>
fooey
<boof/>
</bar:foo>
</par>
</myDoc>
__EOI__

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

# remove namespaces for the whole document
for my $el($doc->findnodes('//*')){
if($el->getNamespaces){
replace_without_ns($el);
}
}

# replaces the given element with an identical one without the namespace
# also does this with attributes
sub replace_without_ns {
my ($el) = @_;
# new element has same name, minus namespace
my $new = XML::LibXML::Element->new( $el->localname );
#copy attributes (minus namespace namespace)
for my $att($el->attributes){
if($att->nodeName !~ /xmlns(?::|$)/){
$new->setAttribute($att->localname, $att->value);
}
}
#move children
for my $child($el->childNodes){
$new->appendChild($child);
}

# if working with the root element, we have to set the new element
# to be the new root
my $doc = $el->ownerDocument;
if( $el->isSameNode($doc->documentElement) ){
$doc->setDocumentElement($new);
return;
}
#otherwise just paste the new element in place of the old element
$el->parentNode->insertAfter($new, $el);
$el->unbindNode;
return;
}

print $doc->toStringHTML;

关于xml - 使用 XML::LibXML 删除 XML 命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17756926/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com