Re: Converting XML to MARC without reading a file?
[email protected] (David Cook) Thu, 19 Apr 2018 10:56:33 +1000
| Newsgroups | perl.perl4lib |
|---|---|
| Message-ID | <CACVmdZSEtikmuW5-n8L8Vk_1OM0ioJc_c2DZZ45XCpkrk1MJYA@mail.gmail.com> |
--94eb2c0d8a40fc4052056a290a74
Content-Type: text/plain; charset="UTF-8"
I've just tested my theory, and it worked great. Here's some code that you
can try at home:
#!/usr/bin/perl
use strict;
use warnings;
use MARC::File::XML;
use MARC::Batch;
my $xml;
while (my $line = <DATA>){
$xml .= $line;
}
open(my $fh, "<", \$xml) or die "Couldn't open file handle: $!";
my $batch = MARC::Batch->new( 'XML', $fh );
while (my $marc = $batch->next() ){
warn $marc->subfield(245,"a");
}
__DATA__
<?xml version="1.0" encoding="UTF-8" ?>
<collection>
<record
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.loc.gov/MARC21/slim
http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
xmlns="http://www.loc.gov/MARC21/slim">
<leader>00740nam a2200253 a 4500</leader>
<datafield tag="245" ind1="1" ind2="0">
<subfield code="a">Test 1</subfield>
</datafield>
</record>
<record
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.loc.gov/MARC21/slim
http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
xmlns="http://www.loc.gov/MARC21/slim">
<leader>00898nam a2200265 a 4500</leader>
<datafield tag="245" ind1="0" ind2="0">
<subfield code="a">Test 2</subfield>
</datafield>
</record>
</collection>
On Thu, Apr 19, 2018 at 10:44 AM, David Cook <[email protected]>
wrote:
> Hey Andy,
>
> That does sound like an annoying problem. Someone else might have a better
> answer, but I think I have a clever solution...
>
> Instead of using MARC::File::XML directly, you can use MARC::Batch instead:
>
> my $batch = MARC::Batch->new( 'XML', $filename );
>
> According to the MARC::Batch documentation, you can actually use a file
> handle instead of a file name: http://search.cpan.org/~
> gmcharlt/MARC-Record-2.0.7/lib/MARC/Batch.pm#new(_$type,_@files_).
>
> You should be able to create an "in-memory" file handle that points to
> your scalar variable holding your XML. Like so:
>
> open(my $fh, "<", \$variable);
>
> You should be able to pass in the $fh to MARC::Batch like this:
>
> my $batch = MARC::Batch->new( 'XML', $fh );
>
> Now I haven't tried this... but in theory it should work.
>
> On Thu, Apr 19, 2018 at 10:25 AM, Andy Kohler <[email protected]>
> wrote:
>
>> Hi -
>>
>> I'm pulling records from the WorldCat Search API in MARCXML, and need to
>> convert them to binary MARC for further evaluation, which I'll do via
>> MARC::Record.
>>
>> Problem: Converting from MARCXML via MARC::File::XML seems to require
>> reading the records from a file. I've already got the XML stored in a
>> variable, retrieved via LWP::Simple->get().
>>
>> Do I have to write the XML to a file, then read it in again to convert
>> it? Or am I just missing something obvious?
>>
>> I've tried things like:
>> $xml = get($api_call); # also verified that $xml now contains MARCXML for
>> 1 or more records
>> my $batch = MARC::File::XML->in($xml);
>> while (my $record = $batch->next()) {
>> print $record;
>> }
>> but I get the error: Can't call method "next" on an undefined value
>>
>> Thanks --Andy
>>
>>
>
--94eb2c0d8a40fc4052056a290a74
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I've just tested my theory, and it worked great. Here&=
#39;s some code that you can try at home:<br><br><div>#!/usr/bin/perl</div>=
<div><br></div><div>use strict;</div><div>use warnings;</div><div>use MARC:=
:File::XML;</div><div>use MARC::Batch;</div><div><br></div><div>my $xml;</d=
iv><div>while (my $line =3D <DATA>){</div><div>=C2=A0 =C2=A0 $xml .=
=3D $line;</div><div>}</div><div>open(my $fh, "<", \$xml) or d=
ie "Couldn't open file handle: $!";</div><div>my $batch =3D M=
ARC::Batch->new( 'XML', $fh );</div><div>while (my $marc =3D $ba=
tch->next() ){</div><div>=C2=A0 =C2=A0 warn $marc->subfield(245,"=
;a");</div><div>}</div><div><br></div><div>__DATA__</div><div><?xml=
version=3D"1.0" encoding=3D"UTF-8" ?></div><div><=
;collection></div><div><record</div><div>=C2=A0 =C2=A0 xmlns:xsi=3D&q=
uot;<a href=3D"http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org=
/2001/XMLSchema-instance</a>"</div><div>=C2=A0 =C2=A0 xsi:schemaLocati=
on=3D"<a href=3D"http://www.loc.gov/MARC21/slim">http://www.loc.gov/MA=
RC21/slim</a> <a href=3D"http://www.loc.gov/standards/marcxml/schema/MARC21=
slim.xsd">http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd</a>&qu=
ot;</div><div>=C2=A0 =C2=A0 xmlns=3D"<a href=3D"http://www.loc.gov/MAR=
C21/slim">http://www.loc.gov/MARC21/slim</a>"></div><div><br></div>=
<div>=C2=A0 <leader>00740nam a2200253 a 4500</leader></div><div=
>=C2=A0 <datafield tag=3D"245" ind1=3D"1" ind2=3D&qu=
ot;0"></div><div>=C2=A0 =C2=A0 <subfield code=3D"a">=
;Test 1</subfield></div><div>=C2=A0 </datafield></div><div><=
/record></div><div><record</div><div>=C2=A0 =C2=A0 xmlns:xsi=3D"=
<a href=3D"http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/200=
1/XMLSchema-instance</a>"</div><div>=C2=A0 =C2=A0 xsi:schemaLocation=
=3D"<a href=3D"http://www.loc.gov/MARC21/slim">http://www.loc.gov/MARC=
21/slim</a> <a href=3D"http://www.loc.gov/standards/marcxml/schema/MARC21sl=
im.xsd">http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd</a>"=
;</div><div>=C2=A0 =C2=A0 xmlns=3D"<a href=3D"http://www.loc.gov/MARC2=
1/slim">http://www.loc.gov/MARC21/slim</a>"></div><div><br></div><d=
iv>=C2=A0 <leader>00898nam a2200265 a 4500</leader></div><div>=
=C2=A0 <datafield tag=3D"245" ind1=3D"0" ind2=3D&quo=
t;0"></div><div>=C2=A0 =C2=A0 <subfield code=3D"a">=
Test 2</subfield></div><div>=C2=A0 </datafield></div><div></=
record></div><div></collection></div></div><div class=3D"gmail_ext=
ra"><br><div class=3D"gmail_quote">On Thu, Apr 19, 2018 at 10:44 AM, David =
Cook <span dir=3D"ltr"><<a href=3D"mailto:[email protected]" targ=
et=3D"_blank">[email protected]</a>></span> wrote:<br><blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">Hey Andy,<div><br></div><div>That does=
sound like an annoying problem. Someone else might have a better answer, b=
ut I think I have a clever solution...<br><br>Instead of using MARC::File::=
XML directly, you can use MARC::Batch instead:<br><br>my $batch =3D MARC::B=
atch->new( 'XML', $filename );<br><br>According to the MARC::Bat=
ch documentation, you can actually use a file handle instead of a file name=
:=C2=A0<a href=3D"http://search.cpan.org/~gmcharlt/MARC-Record-2.0.7/lib/MA=
RC/Batch.pm#new(_$type,_@files_)" target=3D"_blank">http://search.cpan.org/=
~<wbr>gmcharlt/MARC-Record-2.0.7/<wbr>lib/MARC/Batch.pm#new(_$type,_<wbr>@f=
iles_)</a>.=C2=A0</div><div><br></div><div>You should be able to create an =
"in-memory" file handle that points to your scalar variable holdi=
ng your XML. Like so:=C2=A0</div><div><br></div><div>open(my $fh, "<=
;", \$variable);</div><div><br></div><div>You should be able to pass i=
n the $fh to MARC::Batch like this:<br><br>
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:s=
mall;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norm=
al;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;background-color:rgb=
(255,255,255);text-decoration-style:initial;text-decoration-color:initial;f=
loat:none;display:inline">my $batch =3D MARC::Batch->new( 'XML',=
$fh );</span>
<br></div><div><br></div><div>Now I haven't tried this... but in theory=
it should work.=C2=A0</div></div><div class=3D"HOEnZb"><div class=3D"h5"><=
div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Thu, Apr 19, 20=
18 at 10:25 AM, Andy Kohler <span dir=3D"ltr"><<a href=3D"mailto:akohler=
[email protected]" target=3D"_blank">[email protected]</a>></span> wrote:=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div><div><div>Hi =
-<br><br></div>I'm pulling records from the WorldCat Search API in MARC=
XML, and need to convert them to binary MARC for further evaluation, which =
I'll do via MARC::Record.<br><br></div>Problem: Converting from MARCXML=
via MARC::File::XML seems to require reading the records from a file.=C2=
=A0 I've already got the XML stored in a variable, retrieved via LWP::S=
imple->get().<br><br></div>Do I have to write the XML to a file, then re=
ad it in again to convert it?=C2=A0 Or am I just missing something obvious?=
<br><br></div><div>I've tried things like:<br></div><div>$xml =3D get($=
api_call); # also verified that $xml now contains MARCXML for 1 or more rec=
ords<br></div><div>my $batch =3D=C2=A0 MARC::File::XML->in($xml);<br>whi=
le (my $record =3D $batch->next()) {<br>=C2=A0 print $record;<br>}<br></=
div><div>but I get the error: Can't call method "next" on an =
undefined value<br><br></div><div>Thanks --Andy<br><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
--94eb2c0d8a40fc4052056a290a74--