2

XML ドキュメントを HTML に変換しています。必要なことの 1 つは、HTML で合法的に宣言できない名前空間の削除です (ルート タグ内の XHTML 名前空間でない限り)。XML::LibXML と LibXML2 でこれを行うのがいかに難しいかについての 5 ~ 10 年前の投稿を見つけましたが、最近はそうではありません。次に例を示します。

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(ドキュメントには、そのメソッドは名前空間を認識していると書かれていますが、明らかに認識していません)。次に、要素の名前空間を null に設定しようとしましたが、それも機能しませんでした。最後に、名前空間を削除する方法についてドキュメントを調べました。そのような幸運はありません。最終的な出力文字列には、削除したいものがすべて含まれています (名前空間の宣言と接頭辞)。

名前空間を削除して、要素と属性を null 名前空間に設定する方法はありますか?

4

2 に答える 2

1

XSLT スタイルシートを使用した簡単なソリューションを次に示します。

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

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);

my $xslt    = XML::LibXSLT->new();
my $xsl_doc = $parser->parse_string(<<'XSL');
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>
XSL

my $stylesheet = $xslt->parse_stylesheet($xsl_doc);
my $result     = $stylesheet->transform($doc);
print $stylesheet->output_as_bytes($result);

コメントまたは処理命令をコピーする場合は、さらに調整が必要になることに注意してください。

于 2015-06-11T16:42:50.830 に答える