develooper Front page | perl.perl6.users | Postings from July 2021

Re: XML module question?

Thread Previous | Thread Next
Bruce Gray
July 16, 2021 16:48
Re: XML module question?
Message ID:
> On Jul 15, 2021, at 11:02 PM, William Michels via perl6-users <> wrote:

(and I re-ordered):

> Any help appreciated,
> Thanks, Bill.

> I'm trying to put an answer together for SO, and I keep running into the same difficulty. Given a CSV file,

Note: input is a log file, not in CSV format.

> how can one produce an XML file with latitude and longitude values properly quoted? Every time I get proper quoting, "lat" and "lon" are scrambled (i.e. sometimes "lat" first, sometimes "lat" second). 
> using the "make-xml()" function from the XML module, I end up scrambling "lat/lon”:

You are using the correct XML module, and you are using it correctly.

Similar to a Raku hash, the attributes in an XML start-tag are *unordered*.
While the inconsistant ordering may be displeasing to our human eyes, any program reading XML should treat your current output identically to your desired output.

In Raku-speak, these two hashes have the same contents:
    my %wpt1 = lat => 'A', lon => 'z';
    my %wpt2 = lon => 'z', lat => 'A’;

Designers of XML libraries are reluctant to add the ability to force an ordering; it would lead to XML-reading programs making improper assumptions.
Like many major XML libraries in other languages, I see no such ability in the Raku XML module.
		Note that the order of attribute specifications
		in a start-tag or empty-element tag is not significant.

> Conversely, if I manage to restrict "lat/lon" to the correct order, I lose the equals sign and proper (value) quotation.

Unless you just hardcode a template and insert the lat/lon/datetime values (never a good idea), you will have to live with the varying order.
I will point out that the XML library also does not output the multi-line indentation that the OP shows; it is irrelevant in XML.

> $ raku -MXML -e 'my @xml = do for lines() {make-xml("wpt", :lat(.words[5].subst(";")), :lon(.words[8]), \("time",.words[0..2]))}; .put for @xml;’  lat_lon.txt

Minor critiques:
That use of `@array = do for lines() {…}` is more commonly written as `@array = lines().map: {…}`
	raku -MXML -e 'my @xml = lines().map: {make-xml("wpt", :lat(.words[5].subst(";")), :lon(.words[8]), \("time",.words[0..2]))}; .put for @xml;'  lat_lon.txt

Nothing is gained by creating an array, just to print each line of the array, so your can just `put` each time you construct an XML line.
	raku -MXML -e 'for lines() { put make-xml("wpt", :lat(.words[5].subst(";")), :lon(.words[8]), \("time",.words[0..2])) }'  lat_lon.txt

When all the output is per-line based on the input, the `-p` or `-n` flag removes the need for `for lines`.
	raku -MXML -ne 'put make-xml("wpt", :lat(.words[5].subst(";")), :lon(.words[8]), \("time",.words[0..2]))'  lat_lon.txt

> So far, I can correctly swap the date/time to the end:
> $ raku -MXML -e 'my @reordered = do for lines() {(.words[3..*],.words[0..2])}; .put for @reordered;’  lat_lon.txt

I am sure that `-MXML` is leftover from other experiments.
Removing `@reordered` and switching to `-n` like my critiques above, this becomes:
	raku -ne 'put (.words[3..*],.words[0..2]);' lat_lon.txt
To “wow” the SO crowd, you might note that @array[N..*],@array[0..N-1] has a shortcut in Raku (.rotate), making this the tightest of all the solutions I see so far:
	raku -ne 'put .words.rotate(3);'  lat_lon.txt

Hope this helps,
Bruce Gray (Util of PerlMonks)

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About