XML :: Twig在同一路径中解析相同的名称标记

时间:2016-08-22 03:17:19

标签: perl xml-parsing xml-twig

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

< ==剪断==>

<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文件中包含更多地址等字段。

&LT; ==剪断==&GT;

以下是我编码的内容:

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只返回标签的中间首字母。 我怎样才能解决第一次出现的“给定”并将其分配给$ fields [1]和第二次出现“给出”到$ fields [2] - 或者查看中间的首字母。

另外如何使用XML :: Twig提取“Patient ID”或“birthTime”值 - 我找不到对它的引用。 我尝试使用$ data-&gt; findvalue('birthTime'),但这又回来了。

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

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

很容易从文档中假设您假设使用回调来处理所有事情。但它解析整个文档并完整地查询它同样有效,特别是如果数据量很小

从您的问题中不清楚每位患者是否都有自己的单独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;
}