LibXML:将节点的文本内容更改为null后,喜欢返回缩写节点

时间:2014-05-20 23:43:03

标签: perl libxml2

在我设置一个原始包含一些数据值的节点后,我希望此节点的空/空文本值为缩写形式:

带文字:

<frog>green</frog> 

缩写形式:

<frog/>

当前代码:

 foreach my $child ($node->getChildnodes())
    {
     if ($child->nodeType == XML_TEXT_NODE)
     {
      my $data = $child->getData();
      $data =~ s/(?$case_flag)$sv/$rv/g;
      $child->setData ($data);
      #my $xyz = $parser->parse_balanced_chunk ($node->toString(0))->toString(0);
     }
    }

注释掉的行会返回我想要的内容,但我无法使用缩写标记将其恢复到文档中。

2 个答案:

答案 0 :(得分:2)

缩写标签(例如<frog/>)是除了属性之外没有子节点的元素的一种可能表示。它完全等同于其未缩写的形式(<frog></frog>)。就像你想要的那样,XML :: LibXML会尽可能使用缩写形式。

$ perl -MXML::LibXML -e'
   my $doc = XML::LibXML->new()->parse_string("<root><foo></foo></root>");
   print $doc->toString();
'
<?xml version="1.0"?>
<root><foo/></root>

&#34;尽可能&#34;表示当元素除了属性之外没有子元素时,意味着$node->childNodes()什么都不返回。

但在您的情况下,元素仍然有一个子节点:一个文本节点,其值为空字符串。这可以防止XML :: LibXML缩写元素。如果您希望XML :: LibXML缩写元素,那么如果它是空的,则由您来删除它。修正:

for my $child ($node->getChildnodes()) {
    if ($child->nodeType == XML_TEXT_NODE) {
        my $data = $child->getData();
        $data =~ s/(?$case_flag)$sv/$rv/g;
        if ($data eq "") {
            $node->removeChild($child);
        } else {
            $child->setData($data);
        }
    }
}

以下是我用于测试的代码。

你现在在做什么:

$ perl -MXML::LibXML -e'
   my $doc = XML::LibXML->new()->parse_string("<root><foo> </foo></root>");
   for my $node ($doc->findnodes("//foo")) {
      $_->setData("") for $node->childNodes();
   }
   print $doc->toString();
'
<?xml version="1.0"?>
<root><foo></foo></root>

修复:

$ perl -MXML::LibXML -e'
   my $doc = XML::LibXML->new()->parse_string("<root><foo> </foo></root>");
   for my $node ($doc->findnodes("//foo")) {
      $node->removeChild($_) for $node->childNodes();
   }
   print $doc->toString();
'
<?xml version="1.0"?>
<root><foo/></root>

答案 1 :(得分:1)

缩写标签(例如<frog/>)是除了属性之外没有子节点的元素的一种可能表示。它完全等同于其未缩写的形式(<frog></frog>)。您可以通过传递给构造函数的选项控制一些解析器的输出 - 例如您可以告诉解析器通过'no_blanks'选项删除空节点 - 但是没有选项可以使XML :: LibXML尽可能输出缩写标签。

您可以做的是在序列化XML文档后应用正则表达式:

xyz =~ s{<\s*([^>]+)\s*>\s*</\s*\1\s*>}{<$1/>}g;