Perl LibXML findvalues(...) 连接值

2023-12-01

我正在尝试使用 LibXML 从 XML 文件中提取节点值。当我打电话时findvalue相同元素类型的所有节点都被连接起来。我对使用 LibXML 完全陌生,而且对 Perl 也不是最熟悉。不幸的是,xml 不是最好的。如何提取单个节点?

下面是示例 XML 和输出。 XML 是 iTunes 库导出的片段。

<playlists>
    <dict>
        <key>Name</key><string>Yes - Tales From Topographic Oceans</string>
        <key>Description</key><string></string>
        <key>Playlist ID</key><integer>67312</integer> 
        <key>Playlist Persistent ID</key><string>F28F195257143396</string> 
        <key>All Items</key><true/> 
        <key>Playlist Items</key> 
        <array> 
            <dict>
                <key>Track ID</key><integer>25912</integer>
            </dict>
            <dict>
                <key>Track ID</key><integer>25914</integer>
            </dict>
            <dict>
                <key>Track ID</key><integer>25916</integer>
            </dict>
            <dict>
                <key>Track ID</key><integer>25918</integer>
            </dict>
        </array>
    </dict>
    <dict>
        <key>Name</key><string>Yes - Yessongs</string>
            <key>Description</key><string>Live Album</string>
            <key>Playlist ID</key><integer>67319</integer>
            <key>Playlist Persistent ID</key><string>405B144877D8B8E4</string>
            <key>All Items</key><true/>
            <key>Playlist Items</key>
            <array>
                <dict>
                    <key>Track ID</key><integer>25920</integer>
                </dict>
                <dict>
                    <key>Track ID</key><integer>25922</integer>
                </dict>
                <dict>
                    <key>Track ID</key><integer>25924</integer>
            </dict>

                <dict>
                    <key>Track ID</key><integer>25926</integer>
                </dict>
                <dict>
                    <key>Track ID</key><integer>25928</integer>
                </dict>
                <dict>
                    <key>Track ID</key><integer>25930</integer>
                </dict>
            </array>
    </dict> 
</playlists>

my $dom = XML::LibXML->load_xml(location => $playlistxml);
foreach my $title ($dom->findnodes('//playlists/dict')) {
    my $nodestring = $title->findvalue('./string');
    print $nodestring, "\n";
    foreach my $tracks ($title->findnodes('//playlists/dict/array')) {
        my @trackid = $tracks->findvalue('./dict/integer');
        print @trackid, "\n";
    }
}

这是生成的输出:

Yes - Tales From Topographic OceansF28F195257143396
25912259142591625918
259202592225924259262592825930
Yes - YessongsLive Album405B144877D8B8E4
25912259142591625918
259202592225924259262592825930

期望的输出:

Yes - Tales From Topographic Oceans
25912
25914
25916
25918

Yes - YessongsLive Album
25920
25922
25924
25926
25928
25930

非常感激任何的帮助


按如下方式更改 XPath:

//playlists/dict        →  /playlists/dict
./string                →  key[text()="Name"]/following-sibling::*[1]
//playlists/dict/array  →  key[text()="Playlist Items"]/following-sibling::*[1]/*
./dict/integer          →  key[text()="Track ID"]/following-sibling::*[1]

是的,那些 XPath 非常混乱,但那是因为我们正在处理一个可怕的模式。

Fixed:

use strict;
use warnings;
use feature qw( say );

use XML::LibXML qw( );

my $doc = XML::LibXML->load_xml( location => $ARGV[0] );

my @playlist_nodes = $doc->findnodes('/playlists/dict');
for my $playlist_idx (0..$#$playlist_nodes) {
   my $playlist_node = $playlist_nodes->[$playlist_idx];

   say "" if $playlist_idx;

   my $name = $playlist_node->findvalue('key[text()="Name"]/following-sibling::*[1]');
   say $name;

   for my $track_node ($playlist_node->findnodes('key[text()="Playlist Items"]/following-sibling::*[1]/*')) {
      my $id = $track_node->findvalue('key[text()="Track ID"]/following-sibling::*[1]');
      say $id;
   }
}

上面,我提到所使用的模式很糟糕。设计 XML 模式的人被告知要使用 XML,但他显然不理解 XML。即使模式对 JSON 等任意数据结构进行编码也是很糟糕的。 (This会更好。)无论是谁设计它,只是为了在使用数据之前将数据转换为不同的格式。以下代码执行此操作:

use strict;
use warnings;
use feature qw( say state );

use Carp              qw( croak );
use Types::Serialiser qw( );
use XML::LibXML       qw( );


sub qname {
   my ($node) = @_;
   my $ns   = $node->namespaceURI();
   my $name = $node->nodeName();
   return defined($ns) ? "{$ns}$name" : $name;
}

sub deserialize_array {
   my ($array_node) = @_;
   return [ map { deserialize_value($_) } $array_node->findnodes("*") ];
}

sub deserialize_dict {
   my ($dict_node) = @_;

   my $dict = {};
   my @children = $dict_node->findnodes("*");
   while (@children) {
      my $key_node = shift(@children);
      qname($key_node) eq "key"
         or croak("Expected key");

      my $val_node = shift(@children)
         or croak("Expected value");

      my $key = $key_node->textContent();
      my $val = deserialize_value($val_node);
      $dict->{$key} = $val;
   }

   return $dict;
}

sub deserialize_value {
   my ($val_node) = @_;

   state $deserializers = {
      string  => sub { $_[0]->textContent() },
      integer => sub { 0 + $_[0]->textContent() },
      true    => sub { $Types::Serialiser::true },
      false   => sub { $Types::Serialiser::false },
      array   => \&deserialize_array,
      dict    => \&deserialize_dict,
   };

   my $val_type = qname($val_node);
   my $deserializer = $deserializers->{$val_type}
      or croak("Unrecognized value type \"$val_type\"");

   return $deserializer->($val_node);
}

sub deserialize_doc {
   my ($doc) = @_;
   return deserialize_array($doc->documentElement());
}

有了上面的内容,解决方案就变成了下面这样:

my $doc = XML::LibXML->load_xml( location => $ARGV[0] );
my $playlists = deserialize_doc($doc);

for my $playlist_idx (0..$#$playlists) {
    my $playlist = $playlists->[$playlist_idx];

    say "" if $playlist_idx;

    my $name = $playlist->{"Name"};
    say $name;

    for my $track (@{ $playlist->{"Playlist Items"} }) {
       my $id = $track->{"Track ID"};
       say $id;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Perl LibXML findvalues(...) 连接值 的相关文章

  • 如何用perl逐句读取文本文件?

    我想逐句读取文本文件 我的问题是下面的代码仅根据时期分开 usr bin perl use strict use warnings my file data txt open FILE file my buffer while my sen
  • 如何使用 Perl CGI 脚本提供图像?

    我的 Google fu 让我失望了 如何使用 Perl 提供已生成的图像 Example img src getimage pl getimage pl 里有什么 干得好 usr bin perl w my file inner nav
  • 在 Mac OS X 上安装 libxml2 时出现问题

    我正在尝试在我的 Mac 操作系统 10 6 4 上安装 libxml2 我实际上正在尝试在 Python 中运行 Scrapy 脚本 这需要我安装 Twisted Zope 现在还需要安装 libxml2 我已经下载了最新版本 2 7 7
  • MSMQ接收和删除

    是否有任何选项可以在读取消息后将其从 MSMQ 中删除 比如 接收 删除可以作为原子操作运行吗 听起来您想查看下一条消息 然后在处理完成后接收它 Message message Queue Peek Queue ReceiveById me
  • grep 两个分隔符之间的子字符串

    我有很多bash使用的脚本perl内的表达式grep为了提取两个分隔符之间的子字符串 例子 echo BeginMiddleEnd grep oP lt Begin End 问题是 当我将这些脚本移植到运行的平台时busybox 融合的 g
  • 如何在Android中解析xml类型的HTTPResponse

    我有一个 Android 应用程序 我使用 POST 方法来获取响应 这是我的代码 HttpResponse httpResponse httpclient execute httppost HttpEntity resEntity htt
  • SpreadsheetML 文件扩展名被 IE 和 FF 更改 - 内容类型错误?

    我正在 PHP 中生成 SpreadsheetML 文件 当用户下载文件并保存时 默认情况下文件会另存为 Report xml 并在 Excel 中打开 但是 如果选择在 Excel 中打开文件而不是保存文件 则文件名将更改为 Report
  • Perl 正则表达式图灵完备吗?

    我见过 Ruby 和 Perl 程序员做了一些事情复杂的代码挑战 https codegolf stackexchange com questions 3596 regex validating regex完全用正则表达式 这前瞻和后瞻 h
  • 将 XSD 文件转换为 C# 可序列化类

    我尝试遵循以下答案这个问题 https stackoverflow com questions 87621 how do i map xml to c objects 但无法让 xsd exe 愉快地获取 XSD 文件并将它们转换为类 此处
  • 如何使用XPath选择非空段落?

    我想要抓取的网页具有类似的结构 每个都有一个段落是一个问题 一个段落是一个答案 我想抓取每个问题和答案并将它们存储在两个项目中 问题是 在某些页面上 问题和答案分别是 xxx p 1 and xxx p 2 但在其他页面上 xxx p 1
  • 自定义 XML 文件比较

    我看过很多关于 XML 比较的帖子 但我看过的没有一个能解决我的问题 我们有一些 XML 格式的文本文档 产品描述 带有标题和段落 正在更新 即版本化 我的任务是制作变更摘要 也就是说 我们想要获取两个连续的文件并生成第三个 标题结构 大纲
  • JAXB 不会解组接口列表

    看来 JAXB 无法读取它所写的内容 考虑以下代码 interface IFoo void jump XmlRootElement class Bar implements IFoo XmlElement public String y p
  • 将 LINQ 嵌套到 XML

    我有一些来自遗留应用程序的非标准 XML
  • 使用 XProc 进行 XML 流处理

    我正在玩xproc http www w3 org TR xproc XML 管道语言和http xmlcalabash com http xmlcalabash com 我想找到一个流式传输大型 xml 文档的示例 例如 给定以下内容hu
  • 菜单未显示在应用程序中

    由于某种原因 我的操作菜单在我的 Android Studio 应用程序中消失了 我正在按照教程学习如何创建 Android 应用程序 但最终遇到了这个问题 我正在使用 atm 的教程 http www raywenderlich com
  • Java 中的 XPath 节点集

    我在 eclipse 中有这段代码 NodeSet nodes NodeSet xPath evaluate expression inputSource XPathConstants NODESET 它给我 NodeSet 上的编译时错误
  • 如何更换HXT中的节点?

    给定一个示例 xml 文件
  • 如何从 MySQL 数据查询创建 XML 文件?

    我想知道一种仅使用 MySQL 查询创建 XML 文件的方法 根本不使用任何脚本语言 有关于这个主题的书籍 教程吗 UPDATE 我想澄清一下 我想使用 sql 查询将 XML 数据转发到 php 脚本 Here s 关于从 MySQL S
  • Ebay api GetSellerList,解析响应 XML

    我正在使用 eBay 交易 api 来获取当前列出的卖家股票 我正在使用 GetSellerList 调用 我在解析 xml 时遇到问题 然后将其插入到网站商店中 这是 xml 请求
  • 折叠具有多个字段的行

    我有这个代码 awk seen 1 2 a 1 a 1 a 1 t 2 END for i in a print i a i inputfile 我想折叠具有两个以上字段的行 但始终基于第一个字段作为索引 输入文件 三列制表符分隔 prot

随机推荐

  • 为什么我的 head 选择中的 javascript 代码无法获取元素?

    我已经在 javascript 中研究 pi 计算器很长时间了 我终于完成了 问题是我的头部脚本 document getElementById button addEventListener click function alert Be
  • 媒体查询和设备方向变化

    我有下面的代码 我想要实现的是在移动设备的样式之间切换 将方向从纵向更改为横向 具有大分辨率的设备 如 iPhone 4 或 Galaxy S
  • 是否可以将tornado的gen.engine和gen.Task与twisted一起使用?

    我正在从事的项目都是用 Tornado 编写的 但我添加了一些 Twisted 来处理异步 XML RPC 我想知道您是否可以使用 Tornado 的 gen engine 并使用 Twisted 的代码生成 gen Task 这可能吗 如
  • 使用 jQuery 将每个字符包装在 except 标签中

    我试图将每个文本字符包装在 div div 带有跨度标签 没问题 只是我还需要保持嵌套标签不被修改 因此 如果 DIV 内的字符串是 Some random text b but b wait there s a href http w3
  • 使用 jquery 的改写模式 [关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 如何使我的输入字段就像键盘处于改写模式一样 当用户输入值但没有任何反应时 我尝试使用键盘
  • 如何复制结构并取消引用所有指针

    如何将 Item 结构和所有指针复制到新结构 type Item struct A ASet json a omitempty B BSet json b omitempty C CSet json c omitempty type ASe
  • 工作表中最后使用的单元格

    我是新来的 我希望使用 Excel VBA 返回工作表中最后使用的单元格 我看着使用 VBA 在 Excel 中查找上次使用的单元格时出错 但这并没有回答我遇到的两个问题 The Cells Find Row方法在我的代码中花费的时间太长
  • Svg - 文本元素的颜色背景/覆盖

    我刚刚开始使用 svg 并试图找出样式的局限性 我在 svg 中有一个 svg 文本元素 我的一些文本元素标记有 data editable true 我希望用户能够轻松地看到标记的元素是什么 我正在想象一个简单的 可切换的 半透明的覆盖层
  • 在SQL Server中合并一列中的每两行数据

    我的表结构是 Id UserId EventId 1 1 A 2 1 B 3 1 C 4 1 A 5 1 D 我需要的输出 UserId EventStart EventEnd 1 A B 1 B C 1 C A 1 A D 我希望每两行合
  • C# XML 在 xml 标签后插入注释到 XML

    我正在使用 C 对象来序列化 反序列化 XML 我想在序列化时向 XML 文件添加注释 该注释将是基本注释在标准 xml 标签之后 该注释不需要反序列化 它是一个基本注释 用于指示创建 xml 文件的产品和版本 可以直接序列化成新的X文档
  • 在 C# 中调用 SQL 连接方法

    我正在将此方法调用到我的登录表单 我不知道这有什么问题 我创建了一个名为 MyConnection 的类 该类包含我的 SQL ConnectionString 我想要的是我可以将此函数称为 ex 名为 Myfunction 的 Class
  • 在 Spring Rest 模板中设置超时

    应用程序正在使用 Spring Rest 模板来调用 Web 服务 我正在使用restTemplate exchange url 调用 Web 服务 目前我们没有为此 Web 服务调用传递任何超时值 我如何为 Spring Rest 模板设
  • 我如何使用Python脚本从网站获取pdf链接

    我经常需要从网站下载 pdf 文件 但有时它们不在一页上 他们在分页中划分了链接 我必须单击每一页才能获取链接 我正在学习 python 我想编写一些脚本 我可以在其中放置 web url 并从该网站提取 pdf 链接 我是 python
  • 确保在 StringTemplate 中转义 HTML 实体的最佳方法是什么

    假设有以下字符串模板 给出了 Java Bean 对象的列表 ul people p li p name p email li ul 即人员列表可能包含Person您可能有能力或没有能力增强 扩展的对象 class Person publi
  • 如何使用 ToString() 格式化可为空的 DateTime?

    如何转换可为空的日期时间dt2到格式化字符串 DateTime dt DateTime Now Console WriteLine dt ToString yyyy MM dd hh mm ss works DateTime dt2 Dat
  • 将 JSON 对象转换为另一个对象 - 格式化它

    我想将 JSON 格式的输出转换为另一种格式 我怎样才能做到这一点 例子 旧的 JSON data id e49e183e 9325 4e62 8eda 7e63fb7cdbbd name test id ac310894 d808 447
  • 大于运算符的优化

    信用表和有效交易表有2008年以来的百万条记录数据 我们正在进行迁移 所以我需要找出2017年之后不再使用的credittypeids periodseq 1055 这样就不需要迁移它们 这是查询 gt 部分会导致巨大的成本 请提出替代方案
  • 二维矩阵中各个列的最小-最大归一化

    我有一个包含 4 列 属性和 150 行的数据集 我想使用最小 最大标准化来标准化这些数据 到目前为止 我的代码是 minData min min data1 maxData max max data1 minmaxeddata data1
  • C# 是静态类型还是大部分是静态类型?

    我正在阅读JoeDuffy书中他说 C is a mostly statically typed 我读过的大多数将 C 描述为强类型语言的文章和书籍都有效地使用 强类型 来表示静态类型 真相在哪里 什么是mostly意思是 也许指的是很少有
  • Perl LibXML findvalues(...) 连接值

    我正在尝试使用 LibXML 从 XML 文件中提取节点值 当我打电话时findvalue相同元素类型的所有节点都被连接起来 我对使用 LibXML 完全陌生 而且对 Perl 也不是最熟悉 不幸的是 xml 不是最好的 如何提取单个节点