gpt4 book ai didi

xml - 为什么不鼓励 XML::Simple?

转载 作者:数据小太阳 更新时间:2023-10-29 01:37:09 28 4
gpt4 key购买 nike

来自 XML::Simple 的文档:

The use of this module in new code is discouraged. Other modules are available which provide more straightforward and consistent interfaces. In particular, XML::LibXML is highly recommended.

The major problems with this module are the large number of options and the arbitrary ways in which these options interact - often with unexpected results.


有人可以为我澄清什么是关键原因吗?

最佳答案

真正的问题是什么XML::Simple主要尝试做的是取 XML,并将其表示为 perl 数据结构。

毫无疑问,您会从 perldata 了解到您可用的两个关键数据结构是 hasharray .

  • 数组是有序标量。
  • 散列是无序的键值对。

  • 而 XML 也没有真正做到。它具有以下元素:
  • 非唯一命名(这意味着散列不“适合”)。
  • .... 但在文件中是“有序的”。
  • 可能有属性(你可以插入到散列中)
  • 可能有内容(但可能没有,但可能是一元标签)
  • 可能有 child (任何深度)

  • 而且这些东西不会直接映射到可用的 perl 数据结构 - 在简单的层面上,哈希的嵌套散列可能适合 - 但它无法处理具有重复名称的元素。您也无法轻松区分属性和子节点。

    所以 XML::Simple尝试根据 XML 内容进行猜测,并从各种选项设置中获取“提示”,然后当您尝试输出内容时,它(尝试)反向应用相同的过程。

    结果,对于除最简单的 XML 之外的任何内容,它充其量变得笨拙,或者最糟糕的是丢失数据。

    考虑:
    <xml>
    <parent>
    <child att="some_att">content</child>
    </parent>
    <another_node>
    <another_child some_att="a value" />
    <another_child different_att="different_value">more content</another_child>
    </another_node>
    </xml>

    这 - 当通过 XML::Simple 解析时给你:
    $VAR1 = {
    'parent' => {
    'child' => {
    'att' => 'some_att',
    'content' => 'content'
    }
    },
    'another_node' => {
    'another_child' => [
    {
    'some_att' => 'a value'
    },
    {
    'different_att' => 'different_value',
    'content' => 'more content'
    }
    ]
    }
    };

    注意 - 现在你有以下 parent - 只是匿名哈希,但在 another_node 之下你有一个匿名哈希数组。

    所以为了访问 child的内容:
    my $child = $xml -> {parent} -> {child} -> {content};

    注意你是如何得到一个“子”节点,它下面有一个“内容”节点,这不是因为它是......内容。

    但是要访问第一个 another_child下面的内容元素:
     my $another_child = $xml -> {another_node} -> {another_child} -> [0] -> {content};

    注意如何 - 因为有多个 <another_node>元素,XML 已被解析为一个数组,其中没有一个数组。 (如果您确实在其下方有一个名为 content 的元素,那么您最终会得到其他东西)。您可以使用 ForceArray 更改此设置但是然后你最终得到一个散列数组的散列数组的散列数组 - 尽管它至少在处理子元素时是一致的。编辑:注意,以下讨论 - 这是一个糟糕的默认值,而不是 XML::Simple 的缺陷。

    你应该设置:
    ForceArray => 1, KeyAttr => [], ForceContent => 1

    如果将其应用到上述 XML 中,则会得到:
    $VAR1 = {
    'another_node' => [
    {
    'another_child' => [
    {
    'some_att' => 'a value'
    },
    {
    'different_att' => 'different_value',
    'content' => 'more content'
    }
    ]
    }
    ],
    'parent' => [
    {
    'child' => [
    {
    'att' => 'some_att',
    'content' => 'content'
    }
    ]
    }
    ]
    };

    这将为您提供一致性,因为您将不再拥有与多节点不同的单节点元素处理方式。

    但你仍然:
  • 有一个 5 引用深度树来获得一个值。

  • 例如。:
    print $xml -> {parent} -> [0] -> {child} -> [0] -> {content};

    你还有 contentchild散列元素被视为属性,并且由于散列是无序的,您根本无法重建输入。所以基本上,你必须解析它,然后通过 Dumper 运行它找出你需要看的地方。

    但是有一个 xpath查询,您可以使用以下命令访问该节点:
    findnodes("/xml/parent/child"); 

    你没有得到的东西 XML::Simple您在 XML::Twig 中所做的(我认为 XML::LibXML 但我不太了解):
  • xpath支持。 xpath是一种表示节点路径的 XML 方式。所以你可以用 get_xpath('//child') 在上面“找到”一个节点.您甚至可以在 xpath 中使用属性- 喜欢 get_xpath('//another_child[@different_att]')这将准确选择您想要的那个。 (您也可以迭代匹配项)。
  • cutpaste移动元素
  • parsefile_inplace允许您修改XML与就地编辑。
  • pretty_print选项,格式化 XML .
  • twig_handlerspurge - 这允许您处理非常大的 XML,而无需将其全部加载到内存中。
  • simplify如果你真的必须让它向后兼容 XML::Simple .
  • 代码通常比尝试遵循对散列和数组的引用的菊花链要简单得多,由于结构上的根本差异,这永远无法始终如一地完成。

  • 它也广泛可用 - 可从 CPAN 轻松下载,并在许多操作系统上作为可安装包分发。 (遗憾的是它不是默认安装。然而)

    见: XML::Twig quick reference

    为了比较:
    my $xml = XMLin( \*DATA, ForceArray => 1, KeyAttr => [], ForceContent => 1 );

    print Dumper $xml;
    print $xml ->{parent}->[0]->{child}->[0]->{content};

    对比
    my $twig = XML::Twig->parse( \*DATA );
    print $twig ->get_xpath( '/xml/parent/child', 0 )->text;
    print $twig ->root->first_child('parent')->first_child_text('child');

    关于xml - 为什么不鼓励 XML::Simple?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33267765/

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