jjzjj

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

coder 2024-06-23 原文

来自 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/

    有关xml - 为什么不鼓励 XML::Simple?的更多相关文章

    1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

      为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

    3. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

      我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

    4. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

      如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

    5. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

    6. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

      我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

    7. ruby - 为什么人们使用 `Module.send(:prepend, …)` ? - 2

      我正在学习如何在我的Ruby代码中使用Module.prepend而不是alias_method_chain,我注意到有些人使用send调用它(example):ActionView::TemplateRenderer.send(:prepend,ActionViewTemplateRendererWithCurrentTemplate)而其他人直接调用它(example):ActionView::TemplateRenderer.prepend(ActionViewTemplateRendererWithCurrentTemplate)而且,虽然我还没有看到任何人使用这种风格,但我从

    8. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

      我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

    9. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

      这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

    10. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

      相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

    随机推荐