如何在不知道其结构的情况下阅读xml

时间:2014-05-30 04:10:42

标签: xml

我们是否可以在不知道结构的情况下读取XML文件。我们还可以在节点之间执行某种映射。例如,我的XML将是

<bookstore>
  <location category="US">
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>XYZ</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="sample">
    <title lang="en">Everyday Italian</title>
    <writer>ABCD</writer>
    <year>2005</year>
    <price>30.00</price>
  </book>
 </location>

    <location category="UK">
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="sample">
    <title lang="en">Everyday Italian</title>
    <writer>Giada De Laurentiis</writer>
    <year>2005</year>
    <price>30.00</price>
  </book>
 </location>
</bookstore>

在这个样本XMl中,我想阅读美国及其作者所在地的书店。这里的作者和作者都是明白的,所以我想把作家也视为作者。我想提取作者姓名。(即)输出将是XYZ,ABC。我怎样才能执行这种映射。如何在不知道结构的情况下阅读本文。无论如何都要这样做。这可能吗?首先。如果它是一个愚蠢的问题。

1 个答案:

答案 0 :(得分:0)

这本身并不是一个愚蠢的问题,但如果没有更多细节,很难回答。 XML是一种结构化数据格式。

然而,解析器(如perl s XML::Twig)可以执行诸如遍历和关闭节点之类的操作,并动态地解析结构。所以你可以 - 例如 - 合并authorwriter

E.g。你可以这样做:

use strict;
use warnings;
use XML::Twig;

my %books;

sub process_book {
    my ( $twig, $book ) = @_;
    $book->print;
    print "--\n";
    my $title = $book->first_child('title')->text;
    if ( $books{$title} ) {
        foreach my $element ( $book->children ) {
            if ( not $books{$title}->first_child( $element->tag ) ) {
                my $new_element = $element->cut;
                $new_element->paste( $books{$title} );
            }
        }
        $book->delete;
    }
    else {
        $books{$title} = $book;
    }
}

my $twig = XML::Twig->new(
    pretty_print  => 'indented',
    twig_handlers => { 'book' => \&process_book, },
)->parse( \*DATA );
$twig->print;

__DATA__
<bookstore>
  <location category="US">
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>XYZ</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="sample">
    <title lang="en">Everyday Italian</title>
    <writer>ABCD</writer>
    <year>2005</year>
    <price>30.00</price>
  </book>
 </location>

    <location category="UK">
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="sample">
    <title lang="en">Everyday Italian</title>
    <writer>Giada De Laurentiis</writer>
    <year>2005</year>
    <price>30.00</price>
  </book>
 </location>
</bookstore>

这将贯穿所有书籍并根据标题合并它们。因此,在上面的示例中,您将获得:

<bookstore>
  <location category="US">
    <book category="cooking">
      <writer>ABCD</writer>
      <title lang="en">Everyday Italian</title>
      <author>XYZ</author>
      <year>2005</year>
      <price>30.00</price>
    </book>
  </location>
  <location category="UK"></location>
</bookstore>

我不能更加明确地了解你正在努力完成的事情,但你可以用XML::Twig做一些非常聪明的事情。