The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

XML::Easy::Transform::RationalizeNamespacePrefixes - rationalize namespaces prefixes

SYNOPSIS

  use XML::Easy::Transform::RationalizeNamespacePrefixes qw(
     rationalize_namespace_prefixes
  );

  my $doc = rationalize_namespace_prefixes(
     xml10_read_document($text)
  );

DESCRIPTION

This code creates a new tree of XML::Easy::Element nodes by examining an existing XML::Easy::Element tree and producing a new tree that is schemantically identical under the XML Namespaces 1.0 specification but with all namespace declartions moved to the top node of the tree (this may involve renaming several elements in the tree to have different prefixes.)

It supplies one public function that can do this transformation which is exported on request:

rationalize_namespace_prefixes($easy_element)
rationalize_namespace_prefixes($easy_element, $generator_subref)

The first argument is a XML::Easy::Element that you wish a transformed copy of to be returned. An exception will be thrown if thrown if the XML document is not namespace-well-formed (i.e. it breaches the XML Namespaces 1.0 specification.)

The second (optional) argument is a reference to a function that should, when passed a string containing a xml prefix as its first argument, return a string containing an alternative xml prefix. If no function is passed in then the default renaming function is used, which will append or replace trailing numbers with higher numbers to the prefix.

The new XML::Easy::Element will be returned as the only return value of this function.

EXAMPLES

A Basic Transform

After defining a handy utility function:

  sub process($) {
    return xml10_write_document(
      rationalize_namespace_prefixes(
        xml10_read_document( $_[0] )
      ),"UTF-8"
    );
  }

This code:

  print process <<'XML';
  <foo>
    <ex1:bar xmlns:ex1="http://www.twoshortplanks.com/namespace/example/1"/>
  </foo>
  XML

Moves the namespace up and prints:

  <foo xmlns:ex1="http://www.twoshortplanks.com/namespace/example/1">
    <ex1:bar/>
  </foo>

Creating Prefixes

If you use the same prefix twice in the document to refer to different namespaces then the function will rename one of the prefixes:

  print process <<'XML';
  <muppet:kermit xmlns:muppet="http://www.twoshortplanks.com/namespace/example/muppetshow">
    <muppet:kermit xmlns:muppet="http://www.twoshortplanks.com/namespace/example/seasmestreet" />
  </muppet:kermit>
  XML

Prints

  <muppet:kermit xmlns:muppet="http://www.twoshortplanks.com/namespace/example/muppetshow" xmlns:muppet2="http://www.twoshortplanks.com/namespace/example/seasmestreet">
    <muppet2:kermit />
  </muppet:kermit>

This works for the default namespace too:

  print process <<'XML';
  <foo>
    <bar xmlns="http://www.twoshortplanks.com/namespace/example/1" />
  </foo>
  XML

Prints

  <foo xmlns:default2="http://www.twoshortplanks.com/namespace/example/1">
    <default2:bar />
  </foo>

If you want control on how your prefixes will be renamed you can supply a function as the second arguement to rationalize_namespace_prefixes.

  my $transformed = rationalize_namespace_prefixes(
    $xml_easy_element,
    sub { 
      my $name = shift;
      $name =~ s/\d+\Z//;
      return $name . int(rand(10000));
    }
  );

If your function returns a prefix that has already been used it will be called again and again until it returns an unused prefix. The first time the function is called it will be passed the prefix from the source, and if it is called subsequent times after that because the new prefix it previously returned is already in use it will be passed the prefix the previous call to the function created.

Removing Unneeded Prefixes

This module also removes all unnecessary prefixes:

  <wobble xmlns:ex1="http://www.twoshortplanks.com/namespace/example/1">
    <ex1:wibble ex1:jelly="in my tummy" />
    <ex2:bobble xmlns:ex2="http://www.twoshortplanks.com/namespace/example/1" />
  </wobble>

Will be transformed into

  <wobble xmlns:ex1="http://www.twoshortplanks.com/namespace/example/1">
    <ex1:wibble jelly="in my tummy" />
    <ex1:bobble />
  </wobble>

This said, please note that this module will not replace

AUTHOR

Written by Mark Fowler <mark@twoshortplanks.com>

Copyright Photobox 2009. All Rights Reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

BUGS

Please see http://www.twoshortplanks.com/project/xml-easy-transform-rationalizenamespaceprefix for details of how to submit bugs, access the source control for this project, and contact the author.

SEE ALSO

XML::Easy, http://www.w3.org/TR/REC-xml-names/