Adding to a given XML the XSLT stylesheet declaration with perl + LibXML
-
05-07-2021 - |
Question
Premise: I come from C++ and I'm pretty noob at Perl.
I'm trying to add a stylesheet declaration to a given .xml
file. The .xml
file is created by a third part and downloaded aside; we are not questioning correctness nor well-formedness of the XML. We also can't know if the XML in the file is indented or in one-row.
Not being able to manipulate the file neatly only with Perl, I took XML::LibXML but I'm still stuck. This is so far what I've done.
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $path = './file.xml';
my $fxml = XML::LibXML::Document->new('1.0','utf-8');
my $pi = $fxml->createPI("xml-stylesheet");
$pi->setData(type=>'text/xsl', href=>'trasf.xsl');
$fxml->appendChild($pi);
$XML::LibXML::skipXMLDeclaration = 1;
my $docwodecl = XML::LibXML::Document->new;
$docwodecl = $doc->toString;
open my $out_fh, '>', $path;
print {$out_fh} $final_xml.$docwodecl;
close $out_fh;
With this I only get the XML without the initial declaration <?xml version="1.0" encoding="ISO-8859-1"?>
and the utf-8 characters are all messed up.
I've tried to use something like this
$fxml->setDocumentElement($doc);
$fxml->toFile($path);
but it doesn't work. There's some method i could use to accomplish my (after all pretty simple) goal? I've looked in the docs but I can't find anything useful.
EDIT
The stylesheet declaration have to be after the<?xml version="1.0" encoding="UTF-8"?>
and before the actual XML.
Solution
Change your fxml initialisation to
my $fxml = XML::LibXML->load_xml(location => $path);
You are not loading the original file anywhere.
Update
You can insert the node before the root element by using insertBefore
:
my $path = '1.xml';
my $fxml = XML::LibXML->load_xml(location => $path);
my $pi = $fxml->createPI('xml-stylesheet');
$pi->setData(type => 'text/xsl', href => 'trasf.xsl');
$fxml->insertBefore($pi, $fxml->documentElement);