XML::Twig 正在解析相同路径中的相同名称标签

XML::Twig parsing same name tag in same path

我正在尝试帮助一位对 EMR(电子病历)系统不满意并想转换的客户,但该公司表示他们无法从数据库中提取患者人口统计数据(我们询问他们是否可以在某种 csv 文件中获取我们的姓名、地址、出生日期,非常基本的东西)——但他们声称他们不能这样做。 (考虑到他们正在使用 sql 数据库,这太疯狂了)。 无论如何 - 他们移交患者的方式在 xml 文件中,大约有 40'000 多个。但它们包含的不仅仅是人口统计数据。 在做了一些研究并在 15 年前完成了广泛的 Perl 编程之后(我承认这些年来它已经生锈了) - 我认为这应该是一个用 Perl 完成的好任务 - 我遇到了 XML::Twig 模块似乎可以做到这一点。 不幸的是,感兴趣的 xml 代码如下所示:

<==snip==>

<patient extension="Patient ID Number">  // <--Patient ID is 5 digit number)
  <name>
    <family>Patient Family name</family>
     <given>Patient First/Given name</given>
     <given>Patient Middle Initial</given>
  </name>
  <birthTime value=YEARMMDD"/>

xml 文件中地址 etc.are 的更多字段。

<==snip==>

这是我编码的内容:

my $twig=XML::Twig->new( twig_handlers => {
  'patient/name/family'      => \&get_family_name,
  'patient/name/given'       => \&get_given_name
});
$twig->parsefile('test.xml');

my @fields;

sub get_family_name {my($twig,$data)=@_;$fields[0]=$data->text;$twig->purge;}
sub get_given_name {my($twig,$data)=@_;$fields[1]=$data->text;$twig->purge;}

我可以毫无问题地读出所有具有唯一标签(家庭、城市、邮政编码等)的信息,但 XML:Twig 只有 return 是标签的中间首字母。 例如,我如何处理第一次出现的 "given" 并将其分配给 $fields[1] 和第二次出现的 "given" 给 $fields[2] - 或者去掉中间的首字母。

另外,我如何使用 XML::Twig 提取 "Patient ID" 或 "birthTime" 值 - 我找不到对此的引用。 我尝试使用 $data->findvalue('birthTime') 但结果是空的。

我查看了:Perl, XML::Twig, how to reading field with the same tag 这非常有帮助,但由于重复的标签在同一路径中,所以它是不同的,我似乎找不到答案。 XML::Twig 是否仅 return 在解析文件时找到匹配项时找到的最后一个值?有没有办法提取所有出现的值?

提前感谢您的帮助!

根据文档很容易假设您应该对所有内容使用回调。但是解析整个文档并对其进行整体查询同样有效,尤其是在数据量较小的情况下

从你的问题中不清楚是否每个患者都有一个单独的 XML 文件,并且你没有显示包含 patient 元素的内容,但我建议你使用折衷方法并为 patient 元素编写一个处理程序,提取所有需要的信息

我选择从每个 patient 元素构建一个信息散列 %patient 并将其推送到包含文件中所有数据的数组 @patients 中。如果每个文件只有一名患者,则需要进行更改

我已经解决了 name/given 元素的问题,方法是获取所有元素并将它们连接成一个带有中间空格的字符串。希望合适

这完全未经测试,因为我目前手头只有一台平板电脑,所以要小心。它确实有机会编译,但如果它没有错误我会感到惊讶

use strict;
use warnings 'all';

use XML::Twig;

my @patients;

my $twig = XML::Twig->new(
    twig_handlers => { patient => \&get_patient }
);
$twig->parsefile('test.xml');

sub get_patient {
    my ($twig, $pat) = @_;

    my %patient;

    $patient{id} = $pat>att('extension');

    my $name         = $pat->first_child('name');yy
    $patient{family} = $name->first_child_trimmed_text('family');
    $patient{given}  = join ' ', $name->children_trimmed_text('given');

    $patient{dob}    = $pat->first_child('birthTime')->att('value');

    push @patients, \%patient;
}