Name
     Data::Edit::Xml - Edit data held in Xml format

Synopsis
     use Data::Edit::Xml;

     say STDERR Data::Edit::Xml::new(inputString=><<END)->                          # Docbook
    <sli>
      <li>
        <p>Diagnose the problem</p>
        <p>This can be quite difficult</p>
        <p>Sometimes impossible</p>
      </li>
      <li>
      <p><pre>ls -la</pre></p>
      <p><pre>
    drwxr-xr-x  2 phil phil   4096 Jun 15  2016 Desktop
    drwxr-xr-x  2 phil phil   4096 Nov  9 20:26 Downloads
    </pre></p>
      </li>
    </sli>
    END

     by(sub                                                                         # Transform Docbook to Dita
      {my ($o, $p) = @_;
       if ($o->at(qw(pre p li sli)) and $o->isOnlyChild)
        {$o->change($p->isFirst ? qw(cmd) : qw(stepresult));
         $p->unwrap;
        }
       elsif ($o->at(qw(li sli)) and $o->over(qr(\Ap( p)+\Z)))
        {$_->change($_->isFirst ? qw(cmd) : qw(info)) for $o->contents;
        }
      })->by(sub
      {my ($o) = @_;
       $o->change(qw(step))          if $o->at(qw(li sli));
       $o->change(qw(steps))         if $o->at(qw(sli));
       $o->id = 's'.($o->position+1) if $o->at(qw(step));
       $o->id = 'i'.($o->index+1)    if $o->at(qw(info));
       $o->wrapWith(qw(screen))      if $o->at(qw(CDATA stepresult));
      })->string =~ s/></>\n</gr;

     # Dita (after being formatted for easier reading):
     #
     # <steps>
     #   <step id="s1">
     #     <cmd>Diagnose the problem</cmd>
     #     <info id="i1">This can be quite difficult</info>
     #     <info id="i2">Sometimes impossible</info>
     #     </step>
     #   <step id="s2">
     #     <cmd>ls -la</cmd>
     #     <stepresult>
     #       <screen>
     # drwxr-xr-x  2 phil phil   4096 Jun 15  2016 Desktop
     # drwxr-xr-x  2 phil phil   4096 Nov  9 20:26 Downloads
     #       </screen>
     #     </stepresult>
     #   </step>
     # </steps>

Description
  Constructor
   new()
     New parse - call this method statically as in Data::Edit::Xml::new() with keyword parameters=> chosen from:

      inputString a string of xml to be parsed
      inputFile   a file of xml to be parsed
      name        a symbolic name for this parse used in messages about this parse and to name output files generated by this parse
      output      a directory into which to write output files
      errors      a sub directory of 'output' into which to write a copy of the string to be parsed in the event that an xml parse error is encountered while parsing this string

   cdata()
     The name of the command name to use to represent text

  Stringification
    Print the parse tree

   string($node)
     Build a string from a node of a parse tree and the nodes below it

         Parameter  Description
      1  $node      Start node

   stringWithCondition($node, @conditions)
     Build a string from a node of a parse tree and the nodes below it subject to conditions to reject some nodes

         Parameter    Description
      1  $node        Start node
      2  @conditions  conditions in effect

   addConditions($node, @conditions)
     Add conditions to a node

         Parameter    Description
      1  $node        Node
      2  @conditions  conditions to add

   deleteConditions($node, @conditions)
     Delete conditions applied to a node

         Parameter    Description
      1  $node        Node
      2  @conditions  conditions to add

   listConditions($node)
     List conditions applied to a node

         Parameter  Description
      1  $node      Node

   isText($node)
     Is this a text node?

         Parameter  Description
      1  $node      Node to test

  Attributes
    Get or set attributes

   attr :lvalue($node, $attribute)
     Value of attribute in current command

         Parameter   Description
      1  $node       Node in parse tree
      2  $attribute  attribute name

   setAttr($node, %values)
     Set the value of an attribute in a command

         Parameter  Description
      1  $node      Node in parse tree
      2  %values    (attribute name=>new value)*

  Contents
    Contents of the current node

   contents($node)
     Get all the nodes contained by this node as an array (not an array reference)

         Parameter  Description
      1  $node      Node

   contentBeyond($node)
     Get all the nodes beyond this node at the level of this node

         Parameter  Description
      1  $node      Node

   contentBefore($node)
     Get all the nodes before this node at the level of this node

         Parameter  Description
      1  $node      Node

   contentAsTags($node)
     Get the tags of all the nodes contained by this node as a string

         Parameter  Description
      1  $node      Node

   contentBeyondAsTags($node)
     Get the tags of all the nodes beyond this node as a string

         Parameter  Description
      1  $node      Node

   contentBeforeAsTags($node)
     Get the tags of all the nodes before this node as a string

         Parameter  Description
      1  $node      Node

   position($node)
     Find the position of a node in its parent's content

         Parameter  Description
      1  $node      Node

   index($node)
     Find the position of a node in its parent's index

         Parameter  Description
      1  $node      Node

  Navigation
    Move around in the parse tree

   context($node)
     Tags of this node and its ancestors joined to make a string

         Parameter  Description
      1  $node      Node

   get($node, @position)
     Get a sub node under the current node by its position in each index with position zero assumed if no position is supplied

         Parameter  Description
      1  $node      Node
      2  @position  position specification: (index

   c($node, $tag, $position)
     Get all the nodes with the tag of the specified name below the current node

         Parameter  Description
      1  $node      Node
      2  $tag       tag
      3  $position

   first($node)
     Get the first node below this node

         Parameter  Description
      1  $node      Node

   last($node)
     Get the last node below this node

         Parameter  Description
      1  $node      Node

   isFirst($node)
     Is this node first under its parent?

         Parameter  Description
      1  $node      Node

   isLast($node)
     Is this node last under its parent?

         Parameter  Description
      1  $node      Node

   isOnlyChild($node)
     Is this the only child of its parent?

         Parameter  Description
      1  $node      Node

   next($node)
     Get the node next to the current node

         Parameter  Description
      1  $node      Node

   prev($node)
     Get the node previous to the current node

         Parameter  Description
      1  $node      Node

   by($node, $sub, @context)
     Post-order traversal of a parse tree or sub tree - based on experience this is the most useful way to process xml documents

         Parameter  Description
      1  $node      Starting node
      2  $sub       sub to call for each sub node
      3  @context   accumulated context

   at()
     Check the node is in the context specified by the array of tags from the ancestors going up the parse tree from the node

   over($node, $re)
     Match the tags at the level below a node against a regular expression

         Parameter  Description
      1  $node      Node
      2  $re        regular expression

   after($node, $re)
     Match the tags in the current level after a node against a regular expression

         Parameter  Description
      1  $node      Node
      2  $re        regular expression

   before($node, $re)
     Match the tags in the current level before a node against a regular expression

         Parameter  Description
      1  $node      Node
      2  $re        regular expression

   up($node, @tags)
     Go up to a specified context

         Parameter  Description
      1  $node      Start node
      2  @tags      tags identifying context

  Editing
    Edit the data in the parse tree

   change($node, $name, @tags)
     Change the name of a node in an optional tag context

         Parameter  Description
      1  $node      Node
      2  $name      new name
      3  @tags      tags defining the context

   deleteAttr($node, $attr, $value)
     Delete the attribute, optionally checking its value first

         Parameter  Description
      1  $node      Node
      2  $attr      attribute name
      3  $value     optional attribute value to check first

   renameAttr($node, $old, $new)
     Change the name of an attribute regardless of whether the new attribute already exists

         Parameter  Description
      1  $node      Node
      2  $old       existing attribute name
      3  $new       new attribute name

   changeAttr($node, $old, $new)
     Change the name of an attribute unless it is already there

         Parameter  Description
      1  $node      Node
      2  $old       existing attribute name
      3  $new       new attribute name

   renameAttrValue($node, $old, $oldValue, $new, $newValue)
     Change the name and value of an attribute regardless of whether the new attribute already exists

         Parameter  Description
      1  $node      Node
      2  $old       existing attribute name and value
      3  $oldValue  new attribute name and value
      4  $new
      5  $newValue

   changeAttrValue($node, $old, $oldValue, $new, $newValue)
     Change the name and value of an attribute unless it is already there

         Parameter  Description
      1  $node      Node
      2  $old       existing attribute name and value
      3  $oldValue  new attribute name and value
      4  $new
      5  $newValue

   Structure
    Change the structure of the parse tree

   wrapWith($old, $tag)
     Wrap the original node in a new node forcing the original node down deepening the parse tree

         Parameter  Description
      1  $old       Node
      2  $tag       tag for new node

   wrapContentWith($old, $tag)
     Wrap the content of a node in a new node, the original content then contains the new node which contains the original node's content

         Parameter  Description
      1  $old       Node
      2  $tag       tag for new node

   unwrap($node)
     Unwrap a node by inserting its content into its parent at the point containing the node

         Parameter  Description
      1  $node      Node to unwrap

   replaceWith($old, $new)
     Replace a node (and all its content) with a new node (and all its content)

         Parameter  Description
      1  $old       Old node
      2  $new       new node

   Cut and Put
    Move nodes around in the parse tree

   cut($node)
     Cut out a node - remove the node from the parse tree and return it so that it can be put else where

         Parameter  Description
      1  $node      Node to  cut out

   putNext($old, $new)
     Place the new node just after the original node in the content of the parent

         Parameter  Description
      1  $old       Original node
      2  $new       new node

   putPrev($old, $new)
     Place the new node just before the original node in the content of the parent

         Parameter  Description
      1  $old       Original node
      2  $new       new node

   putFirst($old, $new)
     Place the new node at the front of the content of the original node

         Parameter  Description
      1  $old       Original node
      2  $new       new node

   putLast($old, $new)
     Place the new node at the end of the content of the original node

         Parameter  Description
      1  $old       Original node
      2  $new       new node

Index of methods by name
    "addConditions($node, @conditions)" "after($node, $re)" "at()" "attr
    :lvalue($node, $attribute)" "before($node, $re)" "by($node, $sub,
    @context)" "c($node, $tag, $position)" "cdata()" "change($node, $name,
    @tags)" "changeAttr($node, $old, $new)" "changeAttrValue($node, $old,
    $oldValue, $new, $newValue)" "contentAsTags($node)"
    "contentBefore($node)" "contentBeforeAsTags($node)"
    "contentBeyond($node)" "contentBeyondAsTags($node)" "contents($node)"
    "context($node)" "cut($node)" "deleteAttr($node, $attr, $value)"
    "deleteConditions($node, @conditions)" "first($node)" "get($node,
    @position)" "index($node)" "isFirst($node)" "isLast($node)"
    "isOnlyChild($node)" "isText($node)" "last($node)"
    "listConditions($node)" "new()" "next($node)" "over($node, $re)"
    "position($node)" "prev($node)" "putFirst($old, $new)" "putLast($old,
    $new)" "putNext($old, $new)" "putPrev($old, $new)" "renameAttr($node,
    $old, $new)" "renameAttrValue($node, $old, $oldValue, $new, $newValue)"
    "replaceWith($old, $new)" "setAttr($node, %values)" "string($node)"
    "stringWithCondition($node, @conditions)" "unwrap($node)" "up($node,
    @tags)" "wrapContentWith($old, $tag)" "wrapWith($old, $tag)"

Installation
    This module is written in 100% Pure Perl and is thus easy to read,
    modify and install.

    Standard Module::Build process for building and installing modules:

      perl Build.PL
      ./Build
      ./Build test
      ./Build install

Author
    philiprbrenan@gmail.com

    http://www.appaapps.com

Copyright
    Copyright (c) 2016 Philip R Brenan.

    This module is free software. It may be used, redistributed and/or
    modified under the same terms as Perl itself.

