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

Data::Edit::Xml - Edit data held in the XML format.

Synopsis

Create a new XML parse tree:

  my $a = Data::Edit::Xml::new q(<a><b><c/></b><d><c/></d></a>);

use:

  say STDERR -p $a;

to print:

  <a>
    <b>
      <c/>
    </b>
    <d>
      <c/>
    </d>
  </a>

Cut out c under b but not under d in the created tree by traversing in post-order applying a sub to each node to cut out c when we are at c under b under a.

  $a -> by(sub {$_ -> cut_c_b_a});

Or if you know when you are going:

  $a -> go_b_c__cut;

To get:

  <a>
    <b/>
    <d>
      <c/>
    </d>
  </a>

Bullets to unordered list

To transform a series of bullets into an unordered list, parse the input XML:

  my $a = Data::Edit::Xml::new(<<END);
<a>
<p>• Minimum 1 number</p>
<p>•   No leading, trailing, or embedded spaces</p>
<p>• Not case-sensitive</p>
</a>
END

Traverse the resulting parse tree, removing bullets and leading white space, changing p to li and a to ul:

  $a->change_ul->by(sub
   {$_->up__change_li if $_->text_p and $_->text =~ s/\A•\s*//s
   });

Print to get:

  ok -p $a eq <<END;
<ul>
  <li>Minimum 1 number</li>
  <li>No leading, trailing, or embedded spaces</li>
  <li>Not case-sensitive</li>
</ul>
END

XSLT Transformation Example from Wikipedia

Given sample data for an XSLT transformation from Wikipedia

 my $x = Data::Edit::Xml::new(<<END);
<persons>
  <person username="JS1"><name>John</name><surname>Smith</surname></person>
  <person username="MI1"><name>Morka</name><surname>Ismincius</surname></person>
</persons>
END

We can transform it by the rather shorter:

 $x->by(sub
  {$_->unwrap_name;
   $_->cut_surname;
   $_->change_name_person__change_root_persons;
  });

To get:

 ok -p $x eq <<END;
<persons>
  <name username="JS1">John</name>
  <name username="MI1">Morka</name>
</persons>
END

Convert ol to steps

Given an ordered list:

  my $a = Data::Edit::Xml::new(<<END);
<ol>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ol>
END

A single call transforms the ordered list:

  $a->ditaConvertOlToSubSteps;

to Dita steps:

  ok -p $a eq <<END;
<substeps>
  <substep>
    <cmd>A</cmd>
  </substep>
  <substep>
    <cmd>B</cmd>
  </substep>
  <substep>
    <cmd>C</cmd>
  </substep>
</substeps>
END

Description

Edit data held in the XML format.

Version 20201031.

The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.

Immediately useful methods

These methods are the ones most likely to be of immediate use to anyone using this module for the first time:

at($node, @context)

Confirm that the specified $node has the specified ancestry. Ancestry is specified by providing the expected tags that the $node's parent, the parent's parent etc. must match at each level. If undef is specified then any tag is assumed to match at that level. If a regular expression is specified then the current parent node tag must match the regular expression at that level. If all supplied tags match successfully then the starting node is returned else undef.

attrX($node, $attribute)

Return the value of the specified $attribute of the specified $node or q() if the $node does not have such an attribute.

by($node, $sub)

Post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. A reference to the current node is also made available via $_. This is equivalent to the x= operator.

change($node, $name, @context)

Change the name of the specified $node, optionally confirming that the $node is in a specified context and return the $node.

cut($node, @context)

Cut out and return the specified $node so that it can be reinserted else where in the parse tree.

go($node, @path)

Return the node reached from the specified $node via the specified path: (index position?)* where index is the tag of the next node to be chosen and position is the optional zero based position within the index of those tags under the current node. Position defaults to zero if not specified. Position can also be negative to index back from the top of the index array. * can be used as the last position to retrieve all nodes with the final tag.

moveEndAfter($node, $to, @context)

Move the end of a $node to just after the specified $target node assuming that the $target node is either a subsequent sibling or a child of $node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

new($fileNameOrString, @options)

Create a new parse tree - call this method statically as in Data::Edit::Xml::new(file or string) to parse a file or string or with no parameters and then use "input", "inputFile", "inputString", "errorFile" to provide specific parameters for the parse, then call "parse" to perform the parse and return the parse tree.

prettyString($node, $depth)

Return a readable string representing a node of a parse tree and all the nodes below it. Or use -p $node

putLast($old, $new, @context)

Place a cut out or new node last in the content of the specified $node and return the new node. See putLastCut to cut and put last in one operation. See addLast to perform this operation conditionally.

putNextRequiredCleanUp($node, @text)

Place a required cleanup next after a specified $node using the specified @text and return the required clean up node.

unwrap($node, @context)

Unwrap the specified $node if in the optional @context by replacing the node with its contents. Returns the parent node on success, otherwise undef if an attempt is made to unwrap a text node or the root node.

wrapWith($node, $tag, @context)

Wrap the specified $node in a new node created from the specified $tag in the optional @context forcing the specified $node down to deepen the parse tree - return the new wrapping node or undef if this is not possible. See addWrapWith to perform this operation conditionally.

Construction

Create a parse tree, either by parsing a file or string or node by node or from another parse tree.

File or String

Construct a parse tree from a file or a string.

new($fileNameOrString, @options)

Create a new parse tree - call this method statically as in Data::Edit::Xml::new(file or string) to parse a file or string or with no parameters and then use "input", "inputFile", "inputString", "errorFile" to provide specific parameters for the parse, then call "parse" to perform the parse and return the parse tree.

     Parameter          Description
  1  $fileNameOrString  Optional file name or string from which to construct the parse tree
  2  @options           Hash of other options.

Example:

    my $a = Data::Edit::Xml::new(<<END);                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::new

cdata()

The name of the tag to be used to represent text - this tag must not also be used as a command tag otherwise the parser will confess.

Example:

    ok Data::Edit::Xml::cdata eq q(CDATA);                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

parse($parser)

Parse input Xml specified via: inputFile, input or inputString.

     Parameter  Description
  1  $parser    Parser created by L</new>

Example:

    my $x = Data::Edit::Xml::new;

       $x->inputString = <<END;
  <a id="aa"><b id="bb"><c id="cc"/></b></a>
  END


       $x->parse;                                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


       ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"/>
    </b>
  </a>
  END

Node by Node

Construct a parse tree node by node.

newText(undef, $text)

Create a new text node.

     Parameter  Description
  1  undef      Any reference to this package
  2  $text      Content of new text node

Example:

    ok -p $x eq <<END;
  <a class="aa" id="1">
    <b class="bb" id="2"/>
  </a>
  END


    $x->putLast($x->newText("t"));                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a class="aa" id="1">
    <b class="bb" id="2"/>
  t
  </a>
  END

newTag(undef, $command, %attributes)

Create a new non text node.

     Parameter    Description
  1  undef        Any reference to this package
  2  $command     The tag for the node
  3  %attributes  Attributes as a hash.

Example:

    my $x = Data::Edit::Xml::newTree("a", id=>1, class=>"aa");


    $x->putLast($x->newTag("b", id=>2, class=>"bb"));                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a class="aa" id="1">
    <b class="bb" id="2"/>
  </a>
  END

newTree($command, %attributes)

Create a new tree.

     Parameter    Description
  1  $command     The name of the root node in the tree
  2  %attributes  Attributes of the root node in the tree as a hash.

Example:

    my $x = Data::Edit::Xml::newTree("a", id=>1, class=>"aa");                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $x eq '<a class="aa" id="1"/>';

dupTag($node, @context)

Create a new non text node by duplicating the tag of an existing node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b><c/></b>
  </a>
  END

    my $d = $a->go_b__dupTag;
    ok -p $d eq <<END;
  <b/>
  END

replaceSpecialChars($string)

Replace < > " & with &lt; &gt; &quot; &amp; Larry Wall's excellent "Xml parser" unfortunately replaces &lt; &gt; &quot; &amp; etc. with their expansions in text by default and does not seem to provide an obvious way to stop this behavior, so we have to put them back again using this method.

     Parameter  Description
  1  $string    String to be edited.

Example:

    ok Data::Edit::Xml::replaceSpecialChars(q(<">)) eq q(&lt;&quot;&gt;);           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::replaceSpecialChars

undoSpecialChars($string)

Reverse the results of calling replaceSpecialChars.

     Parameter  Description
  1  $string    String to be edited.

Example:

    ok Data::Edit::Xml::undoSpecialChars(q(&lt;&quot;&gt;)) eq q(<">);              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::undoSpecialChars

Parse tree attributes

Attributes of a node in a parse tree. For instance the attributes associated with an Xml tag are held in the attributes attribute. It should not be necessary to use these attributes directly unless you are writing an extension to this module. Otherwise you should probably use the methods documented in other sections to manipulate the parse tree as they offer a safer interface at a higher level.

Parse tree

Construct a parse tree from another parse tree.

renew($node, @context)

Returns a renewed copy of the parse tree by first printing it and then reparsing it, optionally checking that the starting node is in a specified context: use this method if you have added nodes via the "Put as text" methods and wish to traverse their parse tree.

Returns the starting node of the new parse tree or undef if the optional context constraint was supplied but not satisfied.

     Parameter  Description
  1  $node      Node to renew from
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new("<a/>", inputFile=>q(aaa.xml));
    $a->putFirstAsText(qq(<b/>));
    ok !$a->go(q(b));

    my $A = $a->renew;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -t $A->go(q(b)) eq q(b);
    ok $A->root->inputFile eq $a->root->inputFile;

clone($tree)

Return a clone of the entire parse tree which is created using the fast Storable::dclone method. The parse tree is cloned without converting it to string and reparsing it so this method will not renew any nodes added as text.

Returns the starting node of the new parse tree.

     Parameter  Description
  1  $tree      Parse tree

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new("<a> </a>");


    my $A = $a->clone;                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $A eq q(<a/>);

    ok $a->equals($A);

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>aaa
      <b>bbb</b>
      ccc
      <d>ddd</d>
      eee
    </a>
  </x>
  END


    my $y = $x->clone;                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$x->diff($y);

equals($node1, $node2)

Return the first node if the two parse trees have identical representations via string, else undef.

     Parameter  Description
  1  $node1     Parse tree 1
  2  $node2     Parse tree 2.

Example:

   {my $a = Data::Edit::Xml::new("<a> </a>");

    my $A = $a->clone;

    ok -s $A eq q(<a/>);


    ok $a->equals($A);                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

equalsIgnoringAttributes($node1, $node2, @attributes)

Return the first node if the two parse trees have identical representations via string if the specified attributes are ignored, else undef.

     Parameter    Description
  1  $node1       Parse tree 1
  2  $node2       Parse tree 2
  3  @attributes  Attributes to ignore during comparison

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b   id="1" outputclass="1" name="b">
      <c id="2" outputclass="2" name="c"/>
    </b>
  </a>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <b   id="11" outputclass="11" name="b">
      <c id="22" outputclass="22" name="c"/>
    </b>
  </a>
  END

    ok !$a->equals($A);


    ok !$a->equalsIgnoringAttributes($A, qw(id));                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a->equalsIgnoringAttributes($A, qw(id outputclass));                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

diff($first, $second, $N)

Return () if the dense string representations of the two nodes are equal, else up to the first N (default 16) characters of the common prefix before the point of divergence and the remainder of the string representation of each node from the point of divergence. All <!-- ... --> comments are ignored during this comparison and all spans of white space are reduced to a single blank.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  $N         Maximum length of difference strings to return

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>aaa
      <b>bbb</b>
      ccc
      <d>ddd</d>
      eee
    </a>
  </x>
  END


    ok !$x->diff($x);                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $y = $x->clone;


    ok !$x->diff($y);                                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    $y->first->putLast($x->newTag(q(f)));

    ok nws(<<END) eq nws(-p $y);
  <x>
    <a>aaa
      <b>bbb</b>
      ccc
      <d>ddd</d>
      eee
      <f/>
    </a>
  </x>
  END


    is_deeply [$x->diff($y)],    ["<d>ddd</d> eee <", "/a></x>", "f/></a></x>"];    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    is_deeply [diff(-p $x, $y)], ["<d>ddd</d> eee <", "/a></x>", "f/></a></x>"];    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    is_deeply [$x->diff(-p $y)], ["<d>ddd</d> eee <", "/a></x>", "f/></a></x>"];    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $X = writeFile(undef, -p $x);

    my $Y = writeFile(undef, -p $y);


    is_deeply [diff($X, $Y)],    ["<d>ddd</d> eee <", "/a></x>", "f/></a></x>"];    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

save($node, $file)

Save a copy of the parse tree to a file which can be restored and return the saved node. This method uses Storable which is fast but produces large files that do not compress well. Use writeCompressedFile to produce smaller save files at the cost of more time.

     Parameter  Description
  1  $node      Parse tree
  2  $file      File.

Example:

      $y->save($f);                                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      my $Y = Data::Edit::Xml::restore($f);

      ok $Y->equals($y);

restore($file)

Return a parse tree from a copy saved in a file by save.

     Parameter  Description
  1  $file      File

Example:

      $y->save($f);


      my $Y = Data::Edit::Xml::restore($f);                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok $Y->equals($y);

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::restore

expandIncludes($x)

Expand the includes mentioned in a parse tree: any tag that ends in include is assumed to be an include directive. The file to be included is named on the href keyword. If the file to be included is a relative file name, i.e. it does not begin with / then this file is made absolute relative to the file from which this parse tree was obtained.

     Parameter  Description
  1  $x         Parse tree

Example:

    my @files =

     (owf("in1/a.xml", q(<a id="a"><include href="../in2/b.xml"/></a>)),

      owf("in2/b.xml", q(<b id="b"><include href="c.xml"/></b>)),

      owf("in2/c.xml", q(<c id="c"/>)));

    my $x = Data::Edit::Xml::new(fpf(currentDirectory, $files[0]));


       $x->expandIncludes;                                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <a id="a">
    <b id="b">
      <c id="c"/>
    </b>
  </a>
  END

Print

Create a string representation of the parse tree with optional selection of nodes via conditions.

Normally use the methods in Pretty to format the Xml in a readable yet reparseable manner; use Dense string to format the Xml densely in a reparseable manner; use the other methods to produce unreparseable strings conveniently formatted to assist various specialized operations such as debugging CDATA, using labels or creating tests. A number of the file test operators can also be conveniently used to print parse trees in these formats.

Pretty

Pretty print the parse tree.

prettyString($node, $depth)

Return a readable string representing a node of a parse tree and all the nodes below it. Or use -p $node

     Parameter  Description
  1  $node      Start node
  2  $depth     Optional depth.

Example:

   {my $s = <<END;
  <a>
    <b>
      <A/>
      <B/>
    </b>
    <c>
      <C/>
      <D/>
    </c>
  </a>
  END

    my $a = Data::Edit::Xml::new($s);


    ok $s eq $a->prettyString;                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $s eq -p $a;

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bbb</b>.
    <c>ccc</c>.
  </a>
  END

prettyStringHtml($node, @context)

Return a string of HTML representing a node of a parse tree and all the nodes below it if the node is in the specified context.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a id="1">
    <b id="2" b="B">
      <c/>
    </b>
    <d id="3" d="D">
      Some text
    </d>
  </a>
  END


    ok $a->prettyStringHtml eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <div class="xmlLine"><span class="xmlLineStartTag"></span><span class="xmlLt">&lt;</span><span class="xmlTag">a</span> <span class="xmlAttr">id</span><span class="xmlEquals">=</span><span class="xmlValue">"1"</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLt">&lt;</span><span class="xmlTag">b</span> <span class="xmlAttr">b</span><span class="xmlEquals">=</span><span class="xmlValue">"B"</span> <span class="xmlAttr">id</span><span class="xmlEquals">=</span><span class="xmlValue">"2"</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLt">&lt;</span><span class="xmlTag">c</span><span class="xmlSlashGt">/&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLtSlash">&lt;/</span><span class="xmlTag">b</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLt">&lt;</span><span class="xmlTag">d</span> <span class="xmlAttr">d</span><span class="xmlEquals">=</span><span class="xmlValue">"D"</span> <span class="xmlAttr">id</span><span class="xmlEquals">=</span><span class="xmlValue">"3"</span><span class="xmlGt">&gt;</span><span class="xmlText">Some text</span><span class="xmlLtSlash">&lt;/</span><span class="xmlTag">d</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag"></span><span class="xmlLtSlash">&lt;/</span><span class="xmlTag">a</span><span class="xmlGt">&gt;</span></div>
  END

prettyStringDitaHeaders($node)

Return a readable string representing the parse tree below the specified $node with appropriate headers. Or use -x $node

     Parameter  Description
  1  $node      Start node

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <concept/>
  END

    ok $a->ditaPrettyPrintWithHeaders eq <<END;
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd" []>
  <concept/>
  END

   }

prettyStringNumbered($node, $depth)

Return a readable string representing a node of a parse tree and all the nodes below it with a number attached to each tag. The node numbers can then be used as described in Order to monitor changes to the parse tree.

     Parameter  Description
  1  $node      Start node
  2  $depth     Optional depth.

Example:

   {my $s = <<END;
  <a>
    <b>
      <A/>
      <B/>
    </b>
    <c>
      <C/>
      <D/>
    </c>
  </a>
  END

    $a->numberTree;


    ok $a->prettyStringNumbered eq <<END;                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <a id="1">
    <b id="2">
      <A id="3"/>
      <B id="4"/>
    </b>
    <c id="5">
      <C id="6"/>
      <D id="7"/>
    </c>
  </a>
  END

prettyStringCDATA($node, $depth)

Return a readable string representing a node of a parse tree and all the nodes below it with the text fields wrapped with <CDATA>...</CDATA>.

     Parameter  Description
  1  $node      Start node
  2  $depth     Optional depth.

Example:

    my $a = Data::Edit::Xml::new("<a><b>A</b></a>");

    my $b = $a->first;

       $b->first->replaceWithBlank;


    ok $a->prettyStringCDATA eq <<END;                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <a>
      <b><CDATA> </CDATA></b>
  </a>
  END

prettyStringContent($node)

Return a readable string representing all the nodes below a node of a parse tree.

     Parameter  Description
  1  $node      Start node.

Example:

   {my $s = <<END;
  <a>
    <b>
      <A/>
      <B/>
    </b>
    <c>
      <C/>
      <D/>
    </c>
  </a>
  END


    ok $a->prettyStringContent eq <<END;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <b>
    <A/>
    <B/>
  </b>
  <c>
    <C/>
    <D/>
  </c>
  END

prettyStringContentNumbered($node)

Return a readable string representing all the nodes below a node of a parse tree with numbering added.

     Parameter  Description
  1  $node      Start node.

Example:

   {my $s = <<END;
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    my $a = Data::Edit::Xml::new($s);

    $a->numberTree;


    ok $a->prettyStringContentNumbered eq <<END;                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <b id="2">
    <c id="3"/>
  </b>
  END


    ok $a->go(qw(b))->prettyStringContentNumbered eq <<END;                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <c id="3"/>
  END

xmlHeader($string)

Add the standard Xml header to a string

     Parameter  Description
  1  $string    String to which a standard L<Xml|https://en.wikipedia.org/wiki/XML> header should be prefixed

Example:

  ok xmlHeader("<a/>") eq <<END;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <?xml version="1.0" encoding="UTF-8"?>
  <a/>
  END

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::xmlHeader

Html/Json

Represent the parse tree using html or Json

htmlTables($node)

Return a string of html representing a parse tree.

     Parameter  Description
  1  $node      Start node of parse tree

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <task id="t1">
    <title>Title Text</title>
    <taskbody>
      <context>To add a new configuration:</context>
      <steps>
        <step><cmd>Click<b>Next</b>to go to the next page</cmd></step>
        <step><cmd>On the Ports page, complete the following fields</cmd></step>
        <step><cmd>Click to exit without saving</cmd></step>
      </steps>
      <result>
        <p>good!</p>
      </result>
    </taskbody>
  </task>
  END


    ok stringMd5Sum($a->htmlTables =~ s(#\w+) ()gsr) eq q(1e8555c2ea191a54361cbd8cc5baa94b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok stringMd5Sum($a->jsonString)                  eq q(3afa81dc2b2a249834fbac53a1ebd5f1);

jsonString($node)

Return a Json representation of a parse tree

     Parameter  Description
  1  $node      Start node of parse tree

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <task id="t1">
    <title>Title Text</title>
    <taskbody>
      <context>To add a new configuration:</context>
      <steps>
        <step><cmd>Click<b>Next</b>to go to the next page</cmd></step>
        <step><cmd>On the Ports page, complete the following fields</cmd></step>
        <step><cmd>Click to exit without saving</cmd></step>
      </steps>
      <result>
        <p>good!</p>
      </result>
    </taskbody>
  </task>
  END

    ok stringMd5Sum($a->htmlTables =~ s(#\w+) ()gsr) eq q(1e8555c2ea191a54361cbd8cc5baa94b);

    ok stringMd5Sum($a->jsonString)                  eq q(3afa81dc2b2a249834fbac53a1ebd5f1);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

xmlToJson($xml, $escape)

Return a Json string representing valid Xml contained in a file or string, optionally double escaping escape characters.

     Parameter  Description
  1  $xml       File name or string of valid html
  2  $escape    Double escape the escaped characters if true

Example:

    my $x = <<END;
  <a a="1">t1
    <b b="2" c="3"/>
  t2
  </a>
  END


    ok xmlToJson($x) eq <<'END';  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  {
     "attributes" : {
        "a" : "1"
     },

     "contents" : [
        {
           "tag" : "CDATA",
           "text" : "t1
  "
        },

        {
           "attributes" : {
              "b" : "2",
              "c" : "3"
           },

           "tag" : "b"
        },

        {
           "tag" : "CDATA",
           "text" : "
t2
"
        }
     ],

     "tag" : "a"
  }
  END


    ok xmlToJson($x, 1) eq <<'END';  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  {
     "attributes" : {
        "a" : "1"
     },

     "contents" : [
        {
           "tag" : "CDATA",
           "text" : "t1\
  "
        },

        {
           "attributes" : {
              "b" : "2",
              "c" : "3"
           },

           "tag" : "b"
        },

        {
           "tag" : "CDATA",
           "text" : "\
t2\
"
        }
     ],

     "tag" : "a"
  }
  END

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::xmlToJson

jsonToXml($json)

Convert a json string representing an Xml parse tree into an Xml parse tree

     Parameter  Description
  1  $json      Json string

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a id="a">
    <b id="b" out="out">b1
      <c id="c"/>
      b2
      <d id="d"/>
      b3
    </b>
  </a>
  END

    my                $json = $a->jsonString;
    ok   stringMd5Sum($json) eq q(5bb9140c7076978dfd5f600d68a82164);

    ok -p jsonToXml  ($json) eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <a id="a">
    <b id="b" out="out">b1
      <c id="c"/>
  b2
      <d id="d"/>
  b3
    </b>
  </a>
  END

Dense

Print the parse tree densely for reuse by computers rather than humans.

string($node)

Return a dense string representing a node of a parse tree and all the nodes below it. Or use -s $node.

     Parameter  Description
  1  $node      Start node.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    ok -s $a eq '<a><b><c id="42" match="mm"/></b><d><e/></d></a>';

stringAsMd5Sum($node)

Return the md5 sum of the dense string representing a node of a parse tree minus its id and all the nodes below it. Or use -g $node. The id of the top most node is not included in the md5sum to equate parse trees that would otherwise only differ by the arbitrary root node id value.

     Parameter  Description
  1  $node      Node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      c
    </b>
  </a>
  END


    ok $a->stringAsMd5Sum eq q(390bf05d8f5671cc6a4771834840d695);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok ((-k $a)->id       eq q(GUID-390bf05d-8f56-71cc-6a47-71834840d695));
    ok $a->id             ne (-k $a->first)->id;

stringQuoted($node)

Return a quoted string representing a parse tree a node of a parse tree and all the nodes below it. Or use -o $node.

     Parameter  Description
  1  $node      Start node

Example:

   {my $s = <<END;
  <a>
    <b>
      <A/>
      <B/>
    </b>
    <c>
      <C/>
      <D/>
    </c>
  </a>
  END


    ok $a->stringQuoted eq q('<a><b><A/><B/></b><c><C/><D/></c></a>');              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

stringReplacingIdsWithLabels($node)

Return a string representing the specified parse tree with the id attribute of each node set to the Labels attached to each node.

     Parameter  Description
  1  $node      Start node.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b><c/></b></a>';                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    $b->addLabels(1..4);

    $c->addLabels(5..8);


    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c id="5, 6, 7, 8"/></b></a>';               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    my $s = $x->stringReplacingIdsWithLabels;                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $s eq '<a><b id="1, 2, 3, 4"><c id="5, 6, 7, 8"/></b></a>';

stringExtendingIdsWithLabels($node)

Return a string representing the specified parse tree with the id attribute of each node extended by the Labels attached to each node.

     Parameter  Description
  1  $node      Start node.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a id="a">
    <b id="b">
      <c id="c"/>
    </b>
    <b id="B">
      <c id="C"/>
    </b>
  </a>
  END

    my $N = 0; $a->by(sub{$_->addLabels((-t $_).++$N)});


    ok -p (new $a->stringExtendingIdsWithLabels) eq <<END;                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <a id="a, a5">
    <b id="b, b2">
      <c id="c, c1"/>
    </b>
    <b id="B, b4">
      <c id="C, c3"/>
    </b>
  </a>
  END

stringContent($node)

Return a string representing all the nodes below a node of a parse tree.

     Parameter  Description
  1  $node      Start node.

Example:

   {my $s = <<END;
  <a>
    <b>
      <A/>
      <B/>
    </b>
    <c>
      <C/>
      <D/>
    </c>
  </a>
  END


    ok $a->stringContent eq "<b><A/><B/></b><c><C/><D/></c>";                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

stringContentOrText($node)

Return a string representing all the nodes below a node of a parse tree or the text of the current node if it is a text node.

     Parameter  Description
  1  $node      Start node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>AAAA</a>
  END

    ok $a->stringContent              eq q(AAAA);

    ok $a->stringContentOrText        eq q(AAAA);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $a->first__stringContent       eq q();
    ok $a->first__stringContentOrText eq q(AAAA);

stringNode($node)

Return a string representing the specified $node showing the attributes, labels and node number.

     Parameter  Description
  1  $node      Node.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b><c/></b></a>';

    my $b = $x->go(q(b));

    $b->addLabels(1..2);

    $b->addLabels(3..4);

    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c/></b></a>';

    $b->numberTree;


    ok $b->stringNode eq "b(2) 0:1 1:2 2:3 3:4";                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

stringTagsAndText($node)

Return a string showing just the tags and text at and below a specified $node.

     Parameter  Description
  1  $node      Node.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;

   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

stringText($node)

Return a string showing just the text of the text nodes (separated by blanks) at and below a specified $node.

     Parameter  Description
  1  $node      Node.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;

   is_deeply [$b->stringText],          [qw(cc dd)];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   is_deeply [$B->stringText],          [qw(cc dd)];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

setRepresentationAsTagsAndText($tree)

Sets the representationLast for every node in the specified $tree via stringTagsAndText.

     Parameter  Description
  1  $tree      Tree of nodes.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text

   $a->setRepresentationAsTagsAndText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

setRepresentationAsText($tree)

Sets the representationLast for every node in the specified $tree via stringText.

     Parameter  Description
  1  $tree      Tree of nodes.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text

   $a->setRepresentationAsText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

matchNodesByRepresentation($tree)

Creates a hash of arrays of nodes that have the same representation in the specified $tree. Set representation for each node in the tree before calling this method.

     Parameter  Description
  1  $tree      Tree to examine

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;


   my $m  = $a->matchNodesByRepresentation;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;


   my $M  = $a->matchNodesByRepresentation;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

Conditions

Print a subset of the parse tree determined by the conditions attached to it.

stringWithConditions($node, @conditions)

Return a string representing the specified $node of a parse tree and all the nodes below it subject to conditions to select or reject some nodes.

     Parameter    Description
  1  $node        Start node
  2  @conditions  Conditions to be regarded as in effect.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my $b = $a >= 'b';

    my ($c, $d) = $b->contents;

    $b->addConditions(qw(bb BB));

    $c->addConditions(qw(cc CC));


    ok $a->stringWithConditions         eq '<a><b><c/><d/></b></a>';                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $a->stringWithConditions(qw(bb)) eq '<a><b><d/></b></a>';                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $a->stringWithConditions(qw(cc)) eq '<a/>';                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

condition($node, $condition, @context)

Return the $node if it has the specified $condition and is in the optional @context, else return undef

     Parameter   Description
  1  $node       Node
  2  $condition  Condition to check
  3  @context    Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    $b->addConditions(qw(bb BB));

    $c->addConditions(qw(cc CC));


    ok  $c->condition(q(cc));                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$c->condition(q(dd));                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $c->condition(q(cc), qw(c b a));                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

anyCondition($node, @conditions)

Return the $node if it has any of the specified @conditions, else return undef

     Parameter    Description
  1  $node        Node
  2  @conditions  Conditions to check

Example:

    $b->addConditions(qw(bb BB));

    $c->addConditions(qw(cc CC));


    ok  $b->anyCondition(qw(bb cc));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$b->anyCondition(qw(cc CC));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

allConditions($node, @conditions)

Return the $node if it has all of the specified @conditions, else return undef

     Parameter    Description
  1  $node        Node
  2  @conditions  Conditions to check

Example:

    $b->addConditions(qw(bb BB));

    $c->addConditions(qw(cc CC));


    ok  $b->allConditions(qw(bb BB));                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$b->allConditions(qw(bb cc));                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

addConditions($node, @conditions)

Given a $node add the specified @conditions and return the node.

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

Example:

    $b->addConditions(qw(bb BB));                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok join(' ', $b->listConditions) eq 'BB bb';

deleteConditions($node, @conditions)

Given a $node delete any @conditions applied to the $node and return the $node.

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

Example:

    ok join(' ', $b->listConditions) eq 'BB bb';


    $b->deleteConditions(qw(BB));                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok join(' ', $b->listConditions) eq 'bb';

listConditions($node)

Return a list of conditions applied to a $node.

     Parameter  Description
  1  $node      Node.

Example:

    $b->addConditions(qw(bb BB));


    ok join(' ', $b->listConditions) eq 'BB bb';                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Attributes

Get or set the attributes of nodes in the parse tree. Well Known Attributes can be set directly via lvalue method subs. To set or get the values of other attributes use Get or Set Attributes. To delete or rename attributes see: Other Operations on Attributes.

Well Known Attributes

Get or set these node attributes via lvalue method subs as in:

  $x->href = "#ref";

Get or Set Attributes

Get or set the attributes of nodes.

attr($node, $attribute)

Return the value of an attribute of the current node as an lvalue method sub.

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

Example:

    my $x = Data::Edit::Xml::new(my $s = <<END);
  <a number="1"/>
  END


    ok $x->attr(qq(number)) == 1;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



       $x->attr(qq(number))  = 2;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x->attr(qq(number)) == 2;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $x eq '<a number="2"/>';

attrX($node, $attribute)

Return the value of the specified $attribute of the specified $node or q() if the $node does not have such an attribute.

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

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b name="bb"/></a>));

    my  $b = $a->first;
    ok  $b->attrX_name eq q(bb);
    ok !$b->attrX_bbb;
   }

set($node, %values)

Set the values of some attributes in a node and return the node. Identical in effect to setAttr.

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

Example:

    ok q(<a a="1" b="1" id="aa"/>) eq -s $a;


    $a->set(a=>11, b=>undef, c=>3, d=>4, e=>5);                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   }

addAttr($node, %values)

Check the specified $node for the specified %attributes and add any that are not already set. Returns the current node.

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

Example:

    my $a = Data::Edit::Xml::new(q(<a id="a"/>));


    $a->addAttr(id=>"b", class=>"c");  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq qq(<a class="c" id="a"/>
);

setAttr($node, %values)

Set the values of some attributes in a node and return the node. Identical in effect to set.

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

Example:

    ok -s $x eq '<a number="2"/>';


    $x->setAttr(first=>1, second=>2, last=>undef);                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $x eq '<a first="1" number="2" second="2"/>';

Other Operations on Attributes

Perform operations other than get or set on the attributes of a node

attrs($node, @attributes)

Return the values of the specified attributes of the current node as a list

     Parameter    Description
  1  $node        Node in parse tree
  2  @attributes  Attribute names.

Example:

    ok -s $x eq '<a first="1" number="2" second="2"/>';


    is_deeply [$x->attrs(qw(third second first ))], [undef, 2, 1];                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

attrCount($node, @exclude)

Return the number of attributes in the specified $node, optionally ignoring the specified names from the count.

     Parameter  Description
  1  $node      Node in parse tree
  2  @exclude   Optional attribute names to exclude from the count.

Example:

    ok -s $x eq '<a first="1" number="2" second="2"/>';


    ok $x->attrCount == 3;                                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x->attrCount(qw(first second third)) == 1;                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

getAttrs($node)

Return a sorted list of all the attributes on the specified $node.

     Parameter  Description
  1  $node      Node in parse tree.

Example:

    ok -s $x eq '<a first="1" number="2" second="2"/>';


    is_deeply [$x->getAttrs], [qw(first number second)];                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

deleteAttr($node, $attr, $value)

Delete the named attribute in the specified $node, optionally check its value first, returning the value of the attribute or undef if the attribute does not exist on this node.

     Parameter  Description
  1  $node      Node
  2  $attr      Attribute name
  3  $value     Optional attribute value to check first.

Example:

    ok -s $x eq '<a delete="me" number="2"/>';


    $x->deleteAttr(qq(delete));                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $x eq '<a number="2"/>';

deleteAttrs($node, @attrs)

Delete the specified attributes of the specified $node without checking their values and return the node.

     Parameter  Description
  1  $node      Node
  2  @attrs     Names of the attributes to delete

Example:

    ok -s $x eq '<a first="1" number="2" second="2"/>';


    $x->deleteAttrs(qw(first second third number));                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $x eq '<a/>';

deleteAttrsInTree($node, @attrs)

Delete the specified attributes of the specified $node and all the nodes under it and return the specified $node.

     Parameter  Description
  1  $node      Node
  2  @attrs     Names of the attributes to delete

Example:

    ok -p $a eq <<END;
  <a class="2" id="0">
    <b class="1" id="1">
      <c class="0" id="0">
        <d class="1" id="1"/>
        <e class="2" id="0"/>
        <e class="0" id="1"/>
        <f class="1" id="0"/>
        <f class="2" id="1"/>
      </c>
    </b>
  </a>
  END

    $a->deleteAttrsInTree_class;

    ok -p $a eq <<END
  <a id="0">
    <b id="1">
      <c id="0">
        <d id="1"/>
        <e id="0"/>
        <e id="1"/>
        <f id="0"/>
        <f id="1"/>
      </c>
    </b>
  </a>
  END

attrsNone($node, @context)

Check that the specified $node has no attributes. Return the specified $node if no attributes were found else undef. Invented by MfM.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(q(<a><b/><c id="cc"/></a>));
    ok $a->first__attrsNone;
    ok !$a->last__attrsNone;

deleteAttrValueAtInTree($tree, $attribute, $value, @context)

Delete all instances of the specified $attribute with the specified $value in the specified @context in the specified $tree and return the modified $tree. An undefined $value will cause the attribute to be deleted without first confirming its value. An empty context will remove the attribute from every node in the $tree.

     Parameter   Description
  1  $tree       Tree
  2  $attribute  Attribute name
  3  $value      Attribute value or B<undef> for all values
  4  @context    Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
     <c id="c"/>
     <c id="d"/>
   </b>
   <d>
     <c id="c"/>
     <c id="d"/>
   </d>
  </a>
  END

    $a->deleteAttrValueAtInTree_id_c_c_b;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <c id="d"/>
    </b>
    <d>
      <c id="c"/>
      <c id="d"/>
    </d>
  </a>
  END

renameAttr($node, $old, $new, @context)

Rename attribute $old to $new in the specified $node with optional context @context regardless of whether attribute $new already exists or not and return the $node. To prevent inadvertent changes to an existing attribute use changeAttr.

     Parameter  Description
  1  $node      Node
  2  $old       Existing attribute name
  3  $new       New attribute name
  4  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $x->printAttributes eq qq( no="1" word="first");


    $x->renameAttr(qw(no number));                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->printAttributes eq qq( number="1" word="first");

renameAttrXtr($node, @attr)

Rename the attributes @attr as far as possible to xtrc or xtrf. Returns an array of the attributes that could not be so renamed.

     Parameter  Description
  1  $node      Node
  2  @attr      Attributes to rename if they exist

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(q(<a a="1" b="2" c="3" d="4"/>));
    my @a = $a->renameAttrXtr_a_b_c;
    ok      -A $a eq q(a c="3" d="4" xtrc="1" xtrf="2");
    is_deeply [@a], [qw(c)];

    my $b = Data::Edit::Xml::new(q(<b a="1" b="2" c="3"  d="4" xtrf="5"/>));
    my @b = $b->renameAttrXtr_a_b_c;
    ok      -A $b eq q(b b="2" c="3" d="4" xtrc="1" xtrf="5");
    is_deeply [@b], [qw(b c)];

changeAttr($node, $old, $new, @context)

Rename attribute $old to $new in the specified $node with optional context @context unless attribute $new is already set and return the $node. To make changes regardless of whether the new attribute already exists use renameAttr.

     Parameter  Description
  1  $node      Node
  2  $old       Existing attribute name
  3  $new       New attribute name
  4  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $x->printAttributes eq qq( number="1" word="first");


    $x->changeAttr(qw(number word));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->printAttributes eq qq( number="1" word="first");

changeOrDeleteAttr($node, $old, $new, @context)

Rename attribute $old to $new in the specified $node in the optional @context unless attribute $new is already set in which case delete attribute $old. Return $node regardless of what action was taken. To make changes regardless of whether the new attribute already exists use renameAttr.

     Parameter  Description
  1  $node      Node
  2  $old       Existing attribute name
  3  $new       New attribute name
  4  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a a="1"/>
  END

    $a->changeOrDeleteAttr_a_b;

    ok -p $a eq <<END;
  <a b="1"/>
  END

    my $a = Data::Edit::Xml::new(<<END);
  <a a="1" b="2"/>
  END

    $a->changeOrDeleteAttr_a_b;

    ok -p $a eq <<END;
  <a b="2"/>
  END

renameAttrValue($node, $old, $oldValue, $new, $newValue, @context)

Rename attribute $old to $new with new value $newValue in the specified $node in the optional @context regardless of whether attribute $new already exists or not as long as the attribute $old has the value $oldValue. Return the $node regardless of what changes were made. To prevent inadvertent changes to existing attributes use changeAttrValue.

     Parameter  Description
  1  $node      Node
  2  $old       Existing attribute name
  3  $oldValue  Existing attribute value
  4  $new       New attribute name
  5  $newValue  New attribute value
  6  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $x->printAttributes eq qq( number="1" word="first");


    $x->renameAttrValue(qw(number 1 numeral I));                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->printAttributes eq qq( numeral="I" word="first");

changeAttrValue($node, $old, $oldValue, $new, $newValue, @context)

Rename attribute $old to $new with new value $newValue on the specified $node in the optional @context unless attribute $new is already set or the value of the $old attribute is not $oldValue. Return the $node regardless of what changes were made. To make changes regardless of whether the new attribute already exists use renameAttrValue.

     Parameter  Description
  1  $node      Node
  2  $old       Existing attribute name
  3  $oldValue  Existing attribute value
  4  $new       New attribute name
  5  $newValue  New attribute value
  6  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $x->printAttributes eq qq( numeral="I" word="first");


    $x->changeAttrValue(qw(word second greek mono));                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->printAttributes eq qq( numeral="I" word="first");


    $x->changeAttrValue(qw(word first greek mono));                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->printAttributes eq qq( greek="mono" numeral="I");

changeAttributeValue($node, $attribute, $sub, @context)

Apply a sub to the value of an attribute of the specified $node. The value to be changed is supplied and returned in: $_.

     Parameter   Description
  1  $node       Node
  2  $attribute  Attribute name
  3  $sub        Change sub
  4  @context    Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a aa="abc"/>
  END


    $a->changeAttributeValue(q(aa), sub{s(b) (B)});                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a aa="aBc"/>
  END

changeOrDeleteAttrValue($node, $old, $oldValue, $new, $newValue, @context)

Rename attribute $old to $new with new value $newValue on the specified $node in the optional @context unless attribute $new is already set or the value of the $old attribute is not $oldValue in which cases the $old attribute is deleted. Return the $node regardless of any changes made. To make changes regardless of whether the new attribute already exists use renameAttrValue.

     Parameter  Description
  1  $node      Node
  2  $old       Existing attribute name
  3  $oldValue  Existing attribute value
  4  $new       New attribute name
  5  $newValue  New attribute value
  6  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a a="1"/>
  END

    $a->changeOrDeleteAttrValue_a_0_b_1;

    ok -p $a eq <<END;
  <a a="1"/>
  END

    $a->changeOrDeleteAttrValue_a_1_b_3;

    ok -p $a eq <<END;
  <a b="3"/>
  END

    my $a = Data::Edit::Xml::new(<<END);
  <a a="1" b="2"/>
  END

    $a->changeOrDeleteAttrValue_a_0_b_2;
    ok -p $a eq <<END;
  <a b="2"/>
  END

    my $a = Data::Edit::Xml::new(<<END);
  <a a="1"/>
  END

    $a->changeOrDeleteAttrValue_a_1_b_3;

    ok -p $a eq <<END;
  <a b="3"/>
  END

copyAttrs($source, $target, @attr)

Copy all the attributes of the source node to the target node, or, just the named attributes if the optional list of attributes to copy is supplied, overwriting any existing attributes in the target node and return the source node.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node
  3  @attr      Optional list of attributes to copy

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a a="1" b="2"/>
    <b b="3" c="4"/>
    <c/>
  </x>
  END

    my ($a, $b, $c) = $x->contents;


    $a->copyAttrs($b, qw(aa bb));                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b b="3" c="4"/>
    <c/>
  </x>
  END


    $a->copyAttrs($b);                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b a="1" b="2" c="4"/>
    <c/>
  </x>
  END

copyAttrsFromParent($node, @attr)

Copy all the attributes from the parent (if there is one) of the current $node to $node or just the named @attributes and return $node. If $node is the top of the parse tree then return undef as it does not have a parent.

     Parameter  Description
  1  $node      Node
  2  @attr      Attributes to copy from parent

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a id="a" a="a">
    <b id="b" b="b"/>
  </a>
  END
    my $b = $a->first;
    $b->copyAttrsFromParent_id;
    ok <<END eq -p $a;
  <a a="a" id="a">
    <b b="b" id="a"/>
  </a>
  END


    $b->copyAttrsFromParent;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $a;
  <a a="a" id="a">
    <b a="a" b="b" id="a"/>
  </a>
  END

copyAttrsToParent($node, @attr)

Copy all the attributes of the specified $node to its parent (if there is one) or just the named @attributes and return $node. If $node is the top of the parse tree then return undef as it does not have a parent.

     Parameter  Description
  1  $node      Node
  2  @attr      Attributes to copy from parent

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a a="a">
    <b id="b" b="b"/>
  </a>
  END
    my $b = $a->first;
    $b->copyAttrsToParent_id;
    ok <<END eq -p $a;
  <a a="a" id="b">
    <b b="b" id="b"/>
  </a>
  END


    $b->copyAttrsToParent;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $a;
  <a a="a" b="b" id="b">
    <b b="b" id="b"/>
  </a>
  END

copyNewAttrs($source, $target, @attr)

Copy all the attributes of the source node to the target node, or, just the named attributes if the optional list of attributes to copy is supplied, without overwriting any existing attributes in the target node and return the source node.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node
  3  @attr      Optional list of attributes to copy

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a a="1" b="2"/>
    <b b="3" c="4"/>
    <c/>
  </x>
  END

    my ($a, $b, $c) = $x->contents;


    $a->copyNewAttrs($b, qw(aa bb));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b b="3" c="4"/>
    <c/>
  </x>
  END


    $a->copyNewAttrs($b);                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b a="1" b="3" c="4"/>
    <c/>
  </x>
  END

moveAttrs($source, $target, @attr)

Move all the attributes of the source node to the target node, or, just the named attributes if the optional list of attributes to move is supplied, overwriting any existing attributes in the target node and return the source node.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node
  3  @attr      Attributes to move

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a a="1" b="2"/>
    <b b="3" c="4"/>
    <c/>
  </x>
  END

    my ($a, $b, $c) = $x->contents;


    $a->moveAttrs($c, qw(aa bb));                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b a="1" b="2" c="4"/>
    <c/>
  </x>
  END


    $b->moveAttrs($c);                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b/>
    <c a="1" b="2" c="4"/>
  </x>
  END

moveNewAttrs($source, $target, @attr)

Move all the attributes of the source node to the target node, or, just the named attributes if the optional list of attributes to copy is supplied, without overwriting any existing attributes in the target node and return the source node.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node
  3  @attr      Optional list of attributes to move

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a a="1" b="2"/>
    <b b="3" c="4"/>
    <c/>
  </x>
  END

    my ($a, $b, $c) = $x->contents;


    $b->moveNewAttrs($c, qw(aa bb));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b a="1" b="3" c="4"/>
    <c/>
  </x>
  END


    $b->moveNewAttrs($c);                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b/>
    <c a="1" b="3" c="4"/>
  </x>
  END

    ok <<END eq -p $x;
  <x>
    <c a="1" b="3" c="4"/>
    <b/>
    <a a="1" b="2"/>
  </x>
  END

Traversal

Traverse the parse tree in various orders applying a sub to each node.

Post-order

This order allows you to edit children before their parents.

by($node, $sub)

Post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. A reference to the current node is also made available via $_. This is equivalent to the x= operator.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


     {my $s; $a->by(sub{$s .= $_->tag}); ok $s eq "cbeda"                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

byX($node, $sub)

Post-order traversal of a parse tree calling the specified sub at each node as long as this sub does not die. The traversal is halted if the called sub does die on any call with the reason in ?@ The sub is passed references to the current node and all of its ancestors up to the node on which this sub was called. A reference to the current node is also made available via $_.

Returns the start node regardless of the outcome of calling sub.

     Parameter  Description
  1  $node      Start node
  2  $sub       Sub to call

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


     {my $s; $a->byX(sub{$s .= $_->tag}); ok $s eq "cbeda"                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



  sub byX($$)                                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   {my ($node, $sub) = @_;                                                        # Start node, sub to call
    eval {$node->byX2($sub)};                                                     # Trap any errors that occur
    $node
   }

byList($node, @context)

Return a list of all the nodes at and below a specified $node in post-order or the empty list if the $node is not in the optional @context.

     Parameter  Description
  1  $node      Starting node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    ok -c $e eq q(e d a);

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
    <d/>
   </b>
   <e/>
   <f>
    <g/>
    <h/>
   </f>
  </a>
  END


    ok q(c d b e g h f a) eq join ' ', map{-t $_} $a->byList;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok q(h g f e d c b a) eq join ' ', map{-t $_} $a->byReverseList;
    ok q(a b c d e f g h) eq join ' ', map{-t $_} $a->downList;
    ok q(a f h g e b d c) eq join ' ', map{-t $_} $a->downReverseList;

byReverse($node, $sub, @context)

Reverse post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting $node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node
  3  @context   Accumulated context.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


     {my $s; $a->byReverse(sub{$s .= $_->tag}); ok $s eq "edcba"                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

byReverseX($node, $sub, @context)

Reverse post-order traversal of a parse tree or sub tree below the specified $node calling the specified sub within eval{} at each node and returning the specified starting $node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node
  3  @context   Accumulated context.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

     {my $s; $a->byReverse(sub{$s .= $_->tag}); ok $s eq "edcba"

byReverseList($node, @context)

Return a list of all the nodes at and below a specified $node in reverse preorder or the empty list if the specified $node is not in the optional @context.

     Parameter  Description
  1  $node      Starting node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


      my ($E, $D, $C, $B) = $a->byReverseList;                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -A $C eq q(c id="42" match="mm");

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
    <d/>
   </b>
   <e/>
   <f>
    <g/>
    <h/>
   </f>
  </a>
  END

    ok q(c d b e g h f a) eq join ' ', map{-t $_} $a->byList;

    ok q(h g f e d c b a) eq join ' ', map{-t $_} $a->byReverseList;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok q(a b c d e f g h) eq join ' ', map{-t $_} $a->downList;
    ok q(a f h g e b d c) eq join ' ', map{-t $_} $a->downReverseList;

Pre-order

This order allows you to edit children after their parents

down($node, $sub, @context)

Pre-order traversal down through a parse tree or sub tree calling the specified sub at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node
  3  @context   Accumulated context.

Example:

     {my $s; $a->down(sub{$s .= $_->tag}); ok $s eq "abcde"                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

downX($node, $sub)

Pre-order traversal of a parse tree calling the specified sub at each node as long as this sub does not die. The traversal is halted for the entire parse tree if the called sub does die with the reason returned in ?@. The sub is passed references to the current node and all of its ancestors up to the node on which this sub was called. A reference to the current node is also made available via $_.

Returns the start node regardless of the outcome of calling sub.

     Parameter  Description
  1  $node      Start node
  2  $sub       Sub to call

Example:

     {my $s; $a->down(sub{$s .= $_->tag}); ok $s eq "abcde"


  sub downX($$)                                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   {my ($node, $sub) = @_;                                                        # Start node, sub to call
    eval {$node->downX2($sub)};                                                   # Trap any errors that occur
    $node
   }

downToDie($node, $sub)

Pre-order traversal of a parse tree calling the specified sub at each node as long as this sub does not die. The traversal of the current sub tree is halted and continue with the next sibling or parent if the called sub does die. The sub is passed references to the current node and all of its ancestors up to the node on which this sub was called. A reference to the current node is also made available via $_.

Returns the start node regardless of the outcome of calling sub.

     Parameter  Description
  1  $node      Start node
  2  $sub       Sub to call

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    my @a;

    $a->downToDie(sub  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {confess if -t $_ eq q(b);
      push @a, -t $_;
     });

    is_deeply [@a], [qw(a d e)];

    my @b;

    $a->downToDie(sub  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {confess if -t $_ eq q(c);
      push @b, -t $_;
     });

    is_deeply [@b], [qw(a b d e)];

downList($node, @context)

Return a list of all the nodes at and below a specified $node in pre-order or the empty list if the $node is not in the optional @context.

     Parameter  Description
  1  $node      Starting node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
    <d/>
   </b>
   <e/>
   <f>
    <g/>
    <h/>
   </f>
  </a>
  END

    ok q(c d b e g h f a) eq join ' ', map{-t $_} $a->byList;
    ok q(h g f e d c b a) eq join ' ', map{-t $_} $a->byReverseList;

    ok q(a b c d e f g h) eq join ' ', map{-t $_} $a->downList;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok q(a f h g e b d c) eq join ' ', map{-t $_} $a->downReverseList;

downReverse($node, $sub, @context)

Reverse pre-order traversal down through a parse tree or sub tree calling the specified sub at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node
  3  @context   Accumulated context.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


     {my $s; $a->downReverse(sub{$s .= $_->tag}); ok $s eq "adebc"                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

downReverseX($node, $sub, @context)

Reverse pre-order traversal down through a parse tree or sub tree calling the specified sub within eval{} at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node
  3  @context   Accumulated context.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

     {my $s; $a->downReverse(sub{$s .= $_->tag}); ok $s eq "adebc"

downReverseList($node, @context)

Return a list of all the nodes at and below a specified $node in reverse pre-order or the empty list if the $node is not in the optional @context.

     Parameter  Description
  1  $node      Starting node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
    <d/>
   </b>
   <e/>
   <f>
    <g/>
    <h/>
   </f>
  </a>
  END

    ok q(c d b e g h f a) eq join ' ', map{-t $_} $a->byList;
    ok q(h g f e d c b a) eq join ' ', map{-t $_} $a->byReverseList;
    ok q(a b c d e f g h) eq join ' ', map{-t $_} $a->downList;

    ok q(a f h g e b d c) eq join ' ', map{-t $_} $a->downReverseList;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Pre and Post order

Visit the parent first, then the children, then the parent again.

through($node, $before, $after, @context)

Traverse parse tree visiting each node twice calling the specified sub $before as we go down past the node and sub $after as we go up past the node, finally return the specified starting node. The subs $before, $after are passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $before    Sub to call when we meet a node
  3  $after     Sub to call we leave a node
  4  @context   Accumulated context.

Example:

     {my $s; my $n = sub{$s .= $_->tag}; $a->through($n, $n);                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok $s eq "abccbdeeda"

throughX($node, $before, $after, @context)

Identical to through except the $before, $after subs are called in an eval block to prevent die terminating the traversal of the full tree.

     Parameter  Description
  1  $node      Starting node
  2  $before    Sub to call when we meet a node
  3  $after     Sub to call we leave a node
  4  @context   Accumulated context.

Example:

     {my $s; my $n = sub{$s .= $_->tag}; $a->through($n, $n);

      ok $s eq "abccbdeeda"

Range

Ranges of nodes

from($start, @match)

Return a list consisting of the specified node and its following siblings optionally including only those nodes that match one of the tags in the specified list.

     Parameter  Description
  1  $start     Start node
  2  @match     Optional list of tags to match

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END

     {my ($d, $c, $D) = $a->findByNumbers(5, 7, 10);


      my @f = $d->from;                                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok @f == 4;

      ok $d == $f[0];


      my @F = $d->from(qw(c));                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok @F == 2;

      ok $F[1]->number == 12;

      ok $D == $t[-1];

to($end, @match)

Return a list of the sibling nodes preceding the specified node optionally including only those nodes that match one of the tags in the specified list.

     Parameter  Description
  1  $end       End node
  2  @match     Optional list of tags to match

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END

     {my ($d, $c, $D) = $a->findByNumbers(5, 7, 10);


      my @t = $D->to;                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok @t == 4;


      my @T = $D->to(qw(c));                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok @T == 2;

      ok $T[1]->number == 7;

fromTo($start, $end, @match)

Return a list of the nodes between the specified start and end nodes optionally including only those nodes that match one of the tags in the specified list.

     Parameter  Description
  1  $start     Start node
  2  $end       End node
  3  @match     Optional list of tags to match

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END

     {my ($d, $c, $D) = $a->findByNumbers(5, 7, 10);


      my @r = $d->fromTo($D);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok @r == 3;


      my @R = $d->fromTo($D, qw(c));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok @R == 1;

      ok $R[0]->number == 7;


      ok !$D->fromTo($d);                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



      ok 1 == $d->fromTo($d);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Location

Locate the line numbers and columns of a specified node and write that information as a Oxygen Message.

lineLocation($node)

Return the line number.column location of this tag in its source file or string if the source was parsed with the line number option on.

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END, lineNumbers=>1, inputFile=>q(aaa.xml));
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
  <test id="t1">
   <title>Test_</title>
    <testbody>
      <setup>
        <p>Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks>
        <p>Make sure the pot is on an insulated surface.</p>
      </checks>
      <run>
        <p>Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results>
        <p>Pour the tea into a cup.</p>
      </results>
      <outcome>
        <p>An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok -p $a eq <<END;
  <test id="t1" xtrf="3.1:14">
    <title xtrf="4.2:8">Test_</title>
    <testbody xtrf="5.3:12">
      <setup xtrf="6.5:11">
        <p xtrf="7.7:9">Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks xtrf="9.5:12">
        <p xtrf="10.7:9">Make sure the pot is on an insulated surface.</p>
      </checks>
      <run xtrf="12.5:9">
        <p xtrf="13.7:9">Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results xtrf="15.5:13">
        <p xtrf="16.7:9">Pour the tea into a cup.</p>
      </results>
      <outcome xtrf="18.5:13">
        <p xtrf="19.7:9">An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok $a->go_testbody_run_p__location eq q( on line 13 from 7 to 9 in file: aaa.xml);

    my $p = $a->go_testbody_run_p;
    $p->putNext(my $q = $p->newTag_hello);

    ok $p->lineLocation eq q(on line 13 from 7 to 9);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $q->location eq q( in file: aaa.xml);
    ok $q->closestLocation == $p;
    ok $q->approxLocation eq q( on line 13 from 7 to 9 in file: aaa.xml);

    ok $q->formatOxygenMessage(q(E), q(), q(Hello detected)) eq <<END;
  Type: E
  Line: 13
  Column: 7
  EndLine: 13
  EndColumn: 9
  AdditionalInfoURL:
  Description: Hello detected
  END

location($node, $file)

Return the line number.column plus file location of this tag in its source file or string if the source was parsed with the line number option on.

     Parameter  Description
  1  $node      Node
  2  $file      Optionally the location of the source.

Example:

    my $a = Data::Edit::Xml::new(<<END, lineNumbers=>1, inputFile=>q(aaa.xml));
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
  <test id="t1">
   <title>Test_</title>
    <testbody>
      <setup>
        <p>Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks>
        <p>Make sure the pot is on an insulated surface.</p>
      </checks>
      <run>
        <p>Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results>
        <p>Pour the tea into a cup.</p>
      </results>
      <outcome>
        <p>An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok -p $a eq <<END;
  <test id="t1" xtrf="3.1:14">
    <title xtrf="4.2:8">Test_</title>
    <testbody xtrf="5.3:12">
      <setup xtrf="6.5:11">
        <p xtrf="7.7:9">Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks xtrf="9.5:12">
        <p xtrf="10.7:9">Make sure the pot is on an insulated surface.</p>
      </checks>
      <run xtrf="12.5:9">
        <p xtrf="13.7:9">Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results xtrf="15.5:13">
        <p xtrf="16.7:9">Pour the tea into a cup.</p>
      </results>
      <outcome xtrf="18.5:13">
        <p xtrf="19.7:9">An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok $a->go_testbody_run_p__location eq q( on line 13 from 7 to 9 in file: aaa.xml);

    my $p = $a->go_testbody_run_p;
    $p->putNext(my $q = $p->newTag_hello);
    ok $p->lineLocation eq q(on line 13 from 7 to 9);


    ok $q->location eq q( in file: aaa.xml);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $q->closestLocation == $p;
    ok $q->approxLocation eq q( on line 13 from 7 to 9 in file: aaa.xml);

    ok $q->formatOxygenMessage(q(E), q(), q(Hello detected)) eq <<END;
  Type: E
  Line: 13
  Column: 7
  EndLine: 13
  EndColumn: 9
  AdditionalInfoURL:
  Description: Hello detected
  END

closestLocation($node)

Return the nearest node with line number.column information

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END, lineNumbers=>1, inputFile=>q(aaa.xml));
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
  <test id="t1">
   <title>Test_</title>
    <testbody>
      <setup>
        <p>Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks>
        <p>Make sure the pot is on an insulated surface.</p>
      </checks>
      <run>
        <p>Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results>
        <p>Pour the tea into a cup.</p>
      </results>
      <outcome>
        <p>An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok -p $a eq <<END;
  <test id="t1" xtrf="3.1:14">
    <title xtrf="4.2:8">Test_</title>
    <testbody xtrf="5.3:12">
      <setup xtrf="6.5:11">
        <p xtrf="7.7:9">Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks xtrf="9.5:12">
        <p xtrf="10.7:9">Make sure the pot is on an insulated surface.</p>
      </checks>
      <run xtrf="12.5:9">
        <p xtrf="13.7:9">Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results xtrf="15.5:13">
        <p xtrf="16.7:9">Pour the tea into a cup.</p>
      </results>
      <outcome xtrf="18.5:13">
        <p xtrf="19.7:9">An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok $a->go_testbody_run_p__location eq q( on line 13 from 7 to 9 in file: aaa.xml);

    my $p = $a->go_testbody_run_p;
    $p->putNext(my $q = $p->newTag_hello);
    ok $p->lineLocation eq q(on line 13 from 7 to 9);

    ok $q->location eq q( in file: aaa.xml);

    ok $q->closestLocation == $p;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $q->approxLocation eq q( on line 13 from 7 to 9 in file: aaa.xml);

    ok $q->formatOxygenMessage(q(E), q(), q(Hello detected)) eq <<END;
  Type: E
  Line: 13
  Column: 7
  EndLine: 13
  EndColumn: 9
  AdditionalInfoURL:
  Description: Hello detected
  END

approxLocation($node, $file)

Return the line number.column location of the node nearest to this node in the source file if the source was parsed with the line number option on.

     Parameter  Description
  1  $node      Node
  2  $file      Optionally the location of the source.

Example:

    my $a = Data::Edit::Xml::new(<<END, lineNumbers=>1, inputFile=>q(aaa.xml));
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
  <test id="t1">
   <title>Test_</title>
    <testbody>
      <setup>
        <p>Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks>
        <p>Make sure the pot is on an insulated surface.</p>
      </checks>
      <run>
        <p>Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results>
        <p>Pour the tea into a cup.</p>
      </results>
      <outcome>
        <p>An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok -p $a eq <<END;
  <test id="t1" xtrf="3.1:14">
    <title xtrf="4.2:8">Test_</title>
    <testbody xtrf="5.3:12">
      <setup xtrf="6.5:11">
        <p xtrf="7.7:9">Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks xtrf="9.5:12">
        <p xtrf="10.7:9">Make sure the pot is on an insulated surface.</p>
      </checks>
      <run xtrf="12.5:9">
        <p xtrf="13.7:9">Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results xtrf="15.5:13">
        <p xtrf="16.7:9">Pour the tea into a cup.</p>
      </results>
      <outcome xtrf="18.5:13">
        <p xtrf="19.7:9">An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok $a->go_testbody_run_p__location eq q( on line 13 from 7 to 9 in file: aaa.xml);

    my $p = $a->go_testbody_run_p;
    $p->putNext(my $q = $p->newTag_hello);
    ok $p->lineLocation eq q(on line 13 from 7 to 9);

    ok $q->location eq q( in file: aaa.xml);
    ok $q->closestLocation == $p;

    ok $q->approxLocation eq q( on line 13 from 7 to 9 in file: aaa.xml);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $q->formatOxygenMessage(q(E), q(), q(Hello detected)) eq <<END;
  Type: E
  Line: 13
  Column: 7
  EndLine: 13
  EndColumn: 9
  AdditionalInfoURL:
  Description: Hello detected
  END

formatOxygenMessage($node, $level, $url, @message)

Write an error message in Oxygen format

     Parameter  Description
  1  $node      Node
  2  $level     Error level [F|E|W]
  3  $url       Explanatory Url
  4  @message   Message text

Example:

    my $a = Data::Edit::Xml::new(<<END, lineNumbers=>1, inputFile=>q(aaa.xml));
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
  <test id="t1">
   <title>Test_</title>
    <testbody>
      <setup>
        <p>Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks>
        <p>Make sure the pot is on an insulated surface.</p>
      </checks>
      <run>
        <p>Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results>
        <p>Pour the tea into a cup.</p>
      </results>
      <outcome>
        <p>An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok -p $a eq <<END;
  <test id="t1" xtrf="3.1:14">
    <title xtrf="4.2:8">Test_</title>
    <testbody xtrf="5.3:12">
      <setup xtrf="6.5:11">
        <p xtrf="7.7:9">Place the boiling water and fresh tea in the pot.</p>
      </setup>
      <checks xtrf="9.5:12">
        <p xtrf="10.7:9">Make sure the pot is on an insulated surface.</p>
      </checks>
      <run xtrf="12.5:9">
        <p xtrf="13.7:9">Stir with a spoon then let brew for 5 minutes.</p>
      </run>
      <results xtrf="15.5:13">
        <p xtrf="16.7:9">Pour the tea into a cup.</p>
      </results>
      <outcome xtrf="18.5:13">
        <p xtrf="19.7:9">An enjoyable cup of tea.</p>
      </outcome>
    </testbody>
  </test>
  END

    ok $a->go_testbody_run_p__location eq q( on line 13 from 7 to 9 in file: aaa.xml);

    my $p = $a->go_testbody_run_p;
    $p->putNext(my $q = $p->newTag_hello);
    ok $p->lineLocation eq q(on line 13 from 7 to 9);

    ok $q->location eq q( in file: aaa.xml);
    ok $q->closestLocation == $p;
    ok $q->approxLocation eq q( on line 13 from 7 to 9 in file: aaa.xml);


    ok $q->formatOxygenMessage(q(E), q(), q(Hello detected)) eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Type: E
  Line: 13
  Column: 7
  EndLine: 13
  EndColumn: 9
  AdditionalInfoURL:
  Description: Hello detected
  END

Position

Confirm that the position navigated to is the expected position.

at($node, @context)

Confirm that the specified $node has the specified ancestry. Ancestry is specified by providing the expected tags that the $node's parent, the parent's parent etc. must match at each level. If undef is specified then any tag is assumed to match at that level. If a regular expression is specified then the current parent node tag must match the regular expression at that level. If all supplied tags match successfully then the starting node is returned else undef.

     Parameter  Description
  1  $node      Node
  2  @context   Ancestry.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c> <d/> </c>
      <c> <e/> </c>
      <c> <f/> </c>
    </b>
  </a>
  END


    ok  $a->go(qw(b c -1 f))->at(qw(f c b a));                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a->go(qw(b c  1 e))->at(undef, qr(c|d), undef, qq(a));                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $d->context eq q(d c b a);


    ok  $d->at(qw(d c b), undef);                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->at(qw(d c b), undef, undef);                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->at(qw(d e b));                                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

atText($node, $re, @context)

Confirm that we are on a text node whose text value matches a regular expression in the optional @context. Return the specified $node on success else undef.

     Parameter  Description
  1  $node      Text node
  2  $re        Regular expression to match
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>abcdcba</a>
  END

atStringContentMatches($node, $re, @context)

Confirm that we are on a $node whose contents, represented as a string, matches the specified regular expression $re in the optional @context. Return the specified $node on success else undef.

     Parameter  Description
  1  $node      Text node
  2  $re        Regular expression to match
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc</c>
      <d>dd</d>
    </b>
  </a>
  END

    $a->by(sub
     {my ($o) = @_;
      if (!$o->atStringContentMatches_dd)
       {$o->id = "no";
       }
     });

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="no">cc</c>
      <d>dd</d>
    </b>
  </a>
  END

atTop($node)

Return the current node if it is the root == top of a parse tree else return undef.

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/></a>
  END


    ok  $a->atTop;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok !$a->first__atTop;

attrAt($node, $attribute, @context)

Return the specified $node if it has the specified $attribute and the $node is in the optional @context else return undef.

     Parameter   Description
  1  $node       Starting node
  2  $attribute  Attribute
  3  @context    Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b c="C"/></a>));
    my $b = $a->first;
    ok !$a->attrAt_id;
    ok  $b->attrAt_c_b_a;
    ok !$b->attrAt_b_b_a;
    ok !$b->attrValueAt_c_C_c_a;
    ok  $b->attrValueAt_c_C_b_a;
   }

attrValueAt($node, $attribute, $value, @context)

Return the specified $node if it has the specified $attribute with the specified $value and the $node is in the optional @context else return undef.

     Parameter   Description
  1  $node       Starting node
  2  $attribute  Attribute
  3  $value      Wanted value of attribute
  4  @context    Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b c="C"/></a>));
    my $b = $a->first;
    ok !$a->attrAt_id;
    ok  $b->attrAt_c_b_a;
    ok !$b->attrAt_b_b_a;
    ok !$b->attrValueAt_c_C_c_a;
    ok  $b->attrValueAt_c_C_b_a;
   }

not($node, @tags)

Return the specified $node if it does not match any of the specified tags, else undef

     Parameter  Description
  1  $node      Node
  2  @tags      Tags not to match

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
  </a>
  END

    ok $a->first->not_a_c;

atOrBelow($start, @context)

Confirm that the node or one of its ancestors has the specified context as recognized by at and return the first node that matches the context or undef if none do.

     Parameter  Description
  1  $start     Starting node
  2  @context   Ancestry.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $d->context eq q(d c b a);


    ok  $d->atOrBelow(qw(d c b a));                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $d->atOrBelow(qw(  c b a));                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $d->atOrBelow(qw(    b a));                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->atOrBelow(qw(  c   a));                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

adjacent($first, $second)

Return the first node if it is adjacent to the second node else undef.

     Parameter  Description
  1  $first     First node
  2  $second    Second node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok !$a->adjacent($B);                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $b->adjacent($B);                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

ancestry($node)

Return a list containing: (the specified $node, its parent, its parent's parent etc..). Or use upn to go up the specified number of levels.

     Parameter  Description
  1  $node      Starting node.

Example:

    $a->numberTree;

    ok $a->prettyStringNumbered eq <<END;
  <a id="1">
    <b id="2">
      <A id="3"/>
      <B id="4"/>
    </b>
    <c id="5">
      <C id="6"/>
      <D id="7"/>
    </c>
  </a>
  END


    is_deeply [map {-t $_} $a->findByNumber(7)->ancestry], [qw(D c a)];             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

context($node)

Return a string containing the tag of the starting node and the tags of all its ancestors separated by single spaces.

     Parameter  Description
  1  $node      Starting node.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


    ok $a->go(qw(d e))->context eq 'e d a';                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

containsSingleText($node, @context)

Return the single text element below the specified $node else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new("<a><b>bb</b><c>cc<d/>ee</c></a>");


    ok  $a->go(q(b))->containsSingleText->text eq q(bb);                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->go(q(c))->containsSingleText;                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

depth($node)

Returns the depth of the specified $node, the depth of a root node is zero.

     Parameter  Description
  1  $node      Node.

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END


    ok 0 == $a->depth;                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok 4 == $a->findByNumber(14)->depth;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b><c><d/></c><e/></b></a>));

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
      <e/>
    </b>
  </a>
  END

   my ($d, $c, $e, $b) = $a->byList;
   ok $a->height == 4;

   ok $a->depth  == 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok $c->depth  == 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok $c->height == 2;

   ok $e->depth  == 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok $e->height == 1;

   is_deeply [$a->depthProfile], [qw(4 3 3 2 1)];
  }

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

depthProfile($node)

Returns the depth profile of the tree rooted at the specified $node.

     Parameter  Description
  1  $node      Node.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b><c><d/></c><e/></b></a>));

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
      <e/>
    </b>
  </a>
  END

   my ($d, $c, $e, $b) = $a->byList;
   ok $a->height == 4;
   ok $a->depth  == 0;
   ok $c->depth  == 2;
   ok $c->height == 2;
   ok $e->depth  == 2;
   ok $e->height == 1;


   is_deeply [$a->depthProfile], [qw(4 3 3 2 1)];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  }

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

setDepthProfile($tree)

Sets the depthProfile for every node in the specified $tree. The last set depthProfile for a specific niode can be retrieved from depthProfileLast.

     Parameter  Description
  1  $tree      Tree of nodes.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;


   $a->setDepthProfile;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

height($node)

Returns the height of the tree rooted at the specified $node.

     Parameter  Description
  1  $node      Node.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b><c><d/></c><e/></b></a>));

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
      <e/>
    </b>
  </a>
  END

   my ($d, $c, $e, $b) = $a->byList;

   ok $a->height == 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok $a->depth  == 0;
   ok $c->depth  == 2;

   ok $c->height == 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok $e->depth  == 2;

   ok $e->height == 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   is_deeply [$a->depthProfile], [qw(4 3 3 2 1)];
  }

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>cc
        <d/>
  dd
      </c>
    </b>
    <B>
      <c>cc
        <d/>
  dd
      </c>
    </B>
  </a>
  END

   my $b = $a->first_b; my $B = $a->last_B;
   my $c = $b->first_c; my $C = $B->first_c;
   my $d = $c->first_d; my $D = $C->first_d;

   $a->setDepthProfile;

   ok $b->depthProfileLast eq q(3 3 3 2 1);
   ok $b->depthProfileLast eq $B->depthProfileLast;

  # Represent using tags and text
   $a->setRepresentationAsTagsAndText;
   is_deeply [$b->stringTagsAndText],   [qw(cc d dd c b)];
   is_deeply [$B->stringTagsAndText],   [qw(cc d dd c B)];
   ok         $b->representationLast  eq qq(cc d dd c b);
   ok         $B->representationLast  eq qq(cc d dd c B);
   ok         $c->representationLast  eq qq(cc d dd c);
   ok         $C->representationLast  eq qq(cc d dd c);
   ok dump($b->representationLast) ne dump($B->representationLast);
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $m  = $a->matchNodesByRepresentation;

   my $bb = $b->representationLast;
   is_deeply $m->{$bb}, [$b];

   my $cc = $c->representationLast;
   is_deeply $m->{$cc}, [$c, $C];

  # Represent using just text
   $a->setRepresentationAsText;
   is_deeply [$b->stringText],          [qw(cc dd)];
   is_deeply [$B->stringText],          [qw(cc dd)];
   ok         $b->representationLast  eq qq(cc dd);
   ok         $B->representationLast  eq qq(cc dd);
   is_deeply  $b->representationLast,
              $B->representationLast;
   is_deeply  $c->representationLast,
              $C->representationLast;

   my $M  = $a->matchNodesByRepresentation;
   my $BB = $b->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   my $CC = $c->representationLast;
   is_deeply $M->{$BB}, [$c, $b, $C, $B];

   ok $b->representationLast eq $c->representationLast;
  }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    ok $a->first->isOnlyChildText;
   }

isFirst($node, @context)

Return the specified $node if it is first under its parent and optionally has the specified context, else return undef

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Use isFirstNonBlank to skip a (rare) initial blank text CDATA. Use isFirstNonBlankX to die rather then receive a returned undef or false result.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


    ok $a->go(q(b))->isFirst;                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok  $a->isFirst;                                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isNotFirst($node, @context)

Return the specified $node if it is not first under its parent and optionally has the specified context, else return undef

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/><c/><d/></a>
  END

    my ($b, $c, $d) = $a->byList;

    ok $c->isNotFirst;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $b->isNotLast;

isFirstN($node, $N, @context)

Return the first $N nodes as an array if the first $N tags of the parent of $node finish at the specified $node and have the specified tags in the sequence specified by @context. If @context contains more then $N entries, the remainder are checked as the context of the parent of $node. Returns an array of nodes found or an empty array if the specified $node does not match these conditions.

     Parameter  Description
  1  $node      Node
  2  $N         Number of tags to be first
  3  @context   First tags and optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
    <d/>
    <e/>
  </x>
  END

    my ($a, $b, $c, $d, $e) = $x->byList;

    is_deeply [$b->isFirstN_2_a_b_x], [$a, $b];
    ok !$b->isFirstN_2_b_x;

    is_deeply [$d->isLastN_2_d_e_x], [$d, $e];
    ok !$d->isLastN_2_d_x;

    is_deeply [$b->nextN_3_b_c_d], [$b, $c, $d];
    is_deeply [$d->prevN_3_b_c_d], [$b, $c, $d];

isFirstToDepth($node, $depth, @context)

Return the specified $node if it is first to the specified depth else return undef

     Parameter  Description
  1  $node      Node
  2  $depth     Depth
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $f, $e) = $a->byList;


    ok  $d->isFirstToDepth(4);                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$f->isFirstToDepth(2);                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $f->isFirstToDepth(1);                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$f->isFirstToDepth(3);                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstIs($node, @context)

Return the specified $node if it has one or more child nodes and the first child node has the specified @context otherwise undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/><c/><d/><e/>
  </a>
  END

    ok  $a->go_c__nextIs_d;
    ok !$a->go_c__nextIs_c;
    ok  $a->go_c__prevIs_b;
    ok !$a->go_c__prevIs_e;

    ok  $a->firstIs_b;
    ok !$a->firstIs_c;

    ok  $a->lastIs_e;
    ok !$a->lastIs_d;

isLast($node, @context)

Return the specified $node if it is last under its parent and optionally has the specified context, else return undef

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Use isLastNonBlank to skip a (rare) initial blank text CDATA. Use isLastNonBlankX to die rather then receive a returned undef or false result.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


    ok $a->go(q(d))->isLast;                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok  $a->isLast;                                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isNotLast($node, @context)

Return the specified $node if it is not last under its parent and optionally has the specified context, else return undef

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/><c/><d/></a>
  END

    my ($b, $c, $d) = $a->byList;
    ok $c->isNotFirst;

    ok $b->isNotLast;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isLastN($node, $N, @context)

Return the last $N nodes as an array if the last $N tags of the parent of $node start at the specified $node and have the specified tags in the sequence specified by @context. If @context contains more then $N entries, the remainder are checked as the context of the parent of $node. Returns an array of nodes found or an empty array if the specified $node does not match these conditions.

     Parameter  Description
  1  $node      Node
  2  $N         Number of tags to be last
  3  @context   Last tags and optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
    <d/>
    <e/>
  </x>
  END

    my ($a, $b, $c, $d, $e) = $x->byList;

    is_deeply [$b->isFirstN_2_a_b_x], [$a, $b];
    ok !$b->isFirstN_2_b_x;

    is_deeply [$d->isLastN_2_d_e_x], [$d, $e];
    ok !$d->isLastN_2_d_x;

    is_deeply [$b->nextN_3_b_c_d], [$b, $c, $d];
    is_deeply [$d->prevN_3_b_c_d], [$b, $c, $d];

isLastToDepth($node, $depth, @context)

Return the specified $node if it is last to the specified depth else return undef

     Parameter  Description
  1  $node      Node
  2  $depth     Depth
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $f, $e) = $a->byList;


    ok  $c->isLastToDepth(1);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$c->isLastToDepth(3);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $d->isLastToDepth(2);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->isLastToDepth(4);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastIs($node, @context)

Return the specified $node if it has one or more child nodes and the last child node has the specified @context otherwise undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/><c/><d/><e/>
  </a>
  END

    ok  $a->go_c__nextIs_d;
    ok !$a->go_c__nextIs_c;
    ok  $a->go_c__prevIs_b;
    ok !$a->go_c__prevIs_e;

    ok  $a->firstIs_b;
    ok !$a->firstIs_c;

    ok  $a->lastIs_e;
    ok !$a->lastIs_d;

nextIs($node, @context)

Return the specified $node if there is a following node with the specified @context. Returns undef if the $node is last.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/><c/><d/><e/>
  </a>
  END

    ok  $a->go_c__nextIs_d;
    ok !$a->go_c__nextIs_c;
    ok  $a->go_c__prevIs_b;
    ok !$a->go_c__prevIs_e;

    ok  $a->firstIs_b;
    ok !$a->firstIs_c;

    ok  $a->lastIs_e;
    ok !$a->lastIs_d;

nextN($node, $N, @context)

Return $N nodes as an array starting at $node inclusive if they match the first $N tags of @context. If @context contains more then $N entries, the remainder are checked as the context of the parent of $node. Returns an array of nodes found or an empty array if the specified $node does not match these conditions.

     Parameter  Description
  1  $node      Node
  2  $N         Number of tags to be last
  3  @context   Last tags and optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
    <d/>
    <e/>
  </x>
  END

    my ($a, $b, $c, $d, $e) = $x->byList;

    is_deeply [$b->isFirstN_2_a_b_x], [$a, $b];
    ok !$b->isFirstN_2_b_x;

    is_deeply [$d->isLastN_2_d_e_x], [$d, $e];
    ok !$d->isLastN_2_d_x;

    is_deeply [$b->nextN_3_b_c_d], [$b, $c, $d];
    is_deeply [$d->prevN_3_b_c_d], [$b, $c, $d];

prevIs($node, @context)

Return the specified $node if there is a previous node with the specified @context. Returns undef if the $node is first.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/><c/><d/><e/>
  </a>
  END

    ok  $a->go_c__nextIs_d;
    ok !$a->go_c__nextIs_c;
    ok  $a->go_c__prevIs_b;
    ok !$a->go_c__prevIs_e;

    ok  $a->firstIs_b;
    ok !$a->firstIs_c;

    ok  $a->lastIs_e;
    ok !$a->lastIs_d;

prevN($node, $N, @context)

Return $N nodes as an array ending at $node inclusive if they match the first $N tags of @context. If @context contains more then $N entries, the remainder are checked as the context of the parent of $node. Returns an array of nodes found or an empty array if the specified $node does not match these conditions.

     Parameter  Description
  1  $node      Node
  2  $N         Number of tags to be first
  3  @context   First tags and optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
    <d/>
    <e/>
  </x>
  END

    my ($a, $b, $c, $d, $e) = $x->byList;

    is_deeply [$b->isFirstN_2_a_b_x], [$a, $b];
    ok !$b->isFirstN_2_b_x;

    is_deeply [$d->isLastN_2_d_e_x], [$d, $e];
    ok !$d->isLastN_2_d_x;

    is_deeply [$b->nextN_3_b_c_d], [$b, $c, $d];
    is_deeply [$d->prevN_3_b_c_d], [$b, $c, $d];

isOnlyChild($node, @context)

Return the specified $node if it is the only node under its parent ignoring any surrounding blank text.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $f, $e) = $a->byList;


    ok  $d->isOnlyChild;                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->isOnlyChild(qw(b));                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok  $a->isOnlyChild;                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
    <f>
      <g/>
    </f>
  </a>
  END

isOnlyChildToDepth($node, $depth, @context)

Return the specified $node if it and its ancestors are only children to the specified depth else return undef. isOnlyChildToDepth(1) is the same as isOnlychild

     Parameter  Description
  1  $node      Node
  2  $depth     Depth to which each parent node must also be an only child
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $f, $e) = $a->byList;


    ok  $d->isOnlyChildToDepth(1, qw(d c b a));                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $d->isOnlyChildToDepth(2, qw(d c b a));                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->isOnlyChildToDepth(3, qw(d c b a));                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isOnlyChildN($node, $depth, @context)

Return the specified $node if it is an only child of $depth ancestors with only children in the opptional @context else return undef. isOnlyChildN(1) is the same as isOnlychild.

     Parameter  Description
  1  $node      Node
  2  $depth     Depth to which each parent node must also be an only child
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
    <f>
      <g/>
    </f>
  </a>
  END

isOnlyChildText($node, @context)

Return the specified $node if it is a text node and it is an only child else and its parent is in the specified optional context else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));

    ok $a->first->isOnlyChildText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }

hasSingleChild($node, @context)

Return the only child of the specified $node if the child is the only node under its parent ignoring any surrounding blank text and has the optional specified context, else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b   id="b" b="bb">
      <b id="c" c="cc"/>
    </b>
  </a>
  END

    my ($c, $b) = $a->byList;

    is_deeply [$b->id, $c->id], [qw(b c)];


    ok $c == $b->hasSingleChild;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b == $a->hasSingleChild;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

hasSingleChildText($node, @context)

Return the only child of the specified $node if the child is a text node and the child is the only node under its parent ignoring any surrounding blank text and the child has the optional specified context, else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>aa
    <b>bb</b>
  </a>
  END

    ok !$a->hasSingleChildText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $a->last->hasSingleChildText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

hasSingleChildToDepth($node, $depth, @context)

Return the descendant of the specified $node if it has single children to the specified depth in the specified optional @context else return undef. hasSingleChildToDepth(0) is equivalent to hasSingleChild.

     Parameter  Description
  1  $node      Node
  2  $depth     Depth
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok $h == $g->hasSingleChildToDepth(1);                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $i == $g->hasSingleChildToDepth_2_i_h_g;

    ok      !$g->hasSingleChildToDepth_2_i_h_G;


    ok      !$g->hasSingleChildToDepth(0);                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok      !$g->hasSingleChildToDepth(3);                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $i == $i->hasSingleChildToDepth(0);                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isEmpty($node, @context)

Confirm that the specified $node is empty, that is: the specified $node has no content, not even a blank string of text. To test for blank nodes, see isAllBlankText.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a>

  </a>
  END


    ok $x->isEmpty;                                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $f, $e) = $a->byList;


    ok  $d->isEmpty;                                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    my ($c, $b) = $a->byList;


    ok $c->isEmpty;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $b->hasContent;

hasContent($node, @context)

Confirm that the specified $node has content. Return the specified node if it has content else return undef if it does not.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    my ($c, $b) = $a->byList;

    ok $c->isEmpty;

    ok $b->hasContent;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

over($node, $re, @context)

Confirm that the string representing the tags at the level below the specified $node match a regular expression where each pair of tags is separated by a single space. Use contentAsTags to visualize the tags at the next level.

     Parameter  Description
  1  $node      Node
  2  $re        Regular expression
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(q(b))->over(qr(d.+e));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

over2($node, $re, @context)

Confirm that the string representing the tags at the level below the specified $node match a regular expression where each pair of tags have two spaces between them and the first tag is preceded by a single space and the last tag is followed by a single space. This arrangement simplifies the regular expression used to detect combinations like p+ q? . Use contentAsTags2 to visualize the tags at the next level.

     Parameter  Description
  1  $node      Node
  2  $re        Regular expression
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(q(b))->over2(qr(\A c  d  e  f  g \Z));                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->go(q(b))->contentAsTags  eq q(c d e f g) ;

overAllTags($node, @tags)

Return the specified b<$node> if all of it's child nodes match the specified <@tags> else return undef.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    ok  $a->overAllTags_b_c_d;
    ok !$a->overAllTags_b_c;
    ok !$a->overAllTags_b_c_d_e;
    ok  $a->oat_b_c_d;
    ok !$a->oat_B_c_d;

    ok  $a->overFirstTags_b_c_d;
    ok  $a->overFirstTags_b_c;
    ok !$a->overFirstTags_b_c_d_e;
    ok  $a->oft_b_c;
    ok !$a->oft_B_c;

    ok  $a->overLastTags_b_c_d;
    ok  $a->overLastTags_c_d;
    ok !$a->overLastTags_b_c_d_e;
    ok  $a->olt_c_d;
    ok !$a->olt_C_d;
   }

oat is a synonym for overAllTags.

overFirstTags($node, @tags)

Return the specified b<$node> if the first of it's child nodes match the specified <@tags> else return undef.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    ok  $a->overAllTags_b_c_d;
    ok !$a->overAllTags_b_c;
    ok !$a->overAllTags_b_c_d_e;
    ok  $a->oat_b_c_d;
    ok !$a->oat_B_c_d;

    ok  $a->overFirstTags_b_c_d;
    ok  $a->overFirstTags_b_c;
    ok !$a->overFirstTags_b_c_d_e;
    ok  $a->oft_b_c;
    ok !$a->oft_B_c;

    ok  $a->overLastTags_b_c_d;
    ok  $a->overLastTags_c_d;
    ok !$a->overLastTags_b_c_d_e;
    ok  $a->olt_c_d;
    ok !$a->olt_C_d;
   }

oft is a synonym for overFirstTags.

overLastTags($node, @tags)

Return the specified b<$node> if the last of it's child nodes match the specified <@tags> else return undef.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    ok  $a->overAllTags_b_c_d;
    ok !$a->overAllTags_b_c;
    ok !$a->overAllTags_b_c_d_e;
    ok  $a->oat_b_c_d;
    ok !$a->oat_B_c_d;

    ok  $a->overFirstTags_b_c_d;
    ok  $a->overFirstTags_b_c;
    ok !$a->overFirstTags_b_c_d_e;
    ok  $a->oft_b_c;
    ok !$a->oft_B_c;

    ok  $a->overLastTags_b_c_d;
    ok  $a->overLastTags_c_d;
    ok !$a->overLastTags_b_c_d_e;
    ok  $a->olt_c_d;
    ok !$a->olt_C_d;
   }

olt is a synonym for overLastTags.

matchAfter($node, $re, @context)

Confirm that the string representing the tags following the specified $node matches a regular expression where each pair of tags is separated by a single space. Use contentAfterAsTags to visualize these tags.

     Parameter  Description
  1  $node      Node
  2  $re        Regular expression
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(qw(b e))->matchAfter  (qr(\Af g\Z));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

matchAfter2($node, $re, @context)

Confirm that the string representing the tags following the specified $node matches a regular expression where each pair of tags have two spaces between them and the first tag is preceded by a single space and the last tag is followed by a single space. This arrangement simplifies the regular expression used to detect combinations like p+ q? Use contentAfterAsTags2 to visualize these tags.

     Parameter  Description
  1  $node      Node
  2  $re        Regular expression
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(qw(b e))->matchAfter2 (qr(\A f  g \Z));                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

matchBefore($node, $re, @context)

Confirm that the string representing the tags preceding the specified $node matches a regular expression where each pair of tags is separated by a single space. Use contentBeforeAsTags to visualize these tags.

     Parameter  Description
  1  $node      Node
  2  $re        Regular expression
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(qw(b e))->matchBefore (qr(\Ac d\Z));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

matchBefore2($node, $re, @context)

Confirm that the string representing the tags preceding the specified $node matches a regular expression where each pair of tags have two spaces between them and the first tag is preceded by a single space and the last tag is followed by a single space. This arrangement simplifies the regular expression used to detect combinations like p+ q? Use contentBeforeAsTags2 to visualize these tags.

     Parameter  Description
  1  $node      Node
  2  $re        Regular expression
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(qw(b e))->matchBefore2(qr(\A c  d \Z));                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

parentage($node)

Return a reference to an array of the nodes along the path from the root to the specified $Node inclusive.

     Parameter  Description
  1  $node      Node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    my ($d, $c, $b) = $a->byList;

    is_deeply $a->go_b_c_d__parentage, [$a, $b, $c, $d];

p is a synonym for parentage.

path($node)

Return a list of strings representing the path to a node from the root of the parse tree which can then be reused by go to retrieve the node as long as the structure of the parse tree has not changed along the path.

     Parameter  Description
  1  $node      Node.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END


    is_deeply [$x->go(qw(b d 1 e))->path], [qw(b d 1 e)];                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    $x->by(sub {ok $x->go($_->path) == $_});                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

pathString($node)

Return a string representing the path to the specified $node from the root of the parse tree.

     Parameter  Description
  1  $node      Node.

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END


    ok $a->findByNumber(9)->pathString eq 'b c 1 d e';                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Match

Locate adjacent nodes that match horizontally and vertically

an($node, $current, @context)

Return the next node if the specified $node has the tag specified by $current and the next node is in the specified @context.

     Parameter  Description
  1  $node      Node
  2  $current   Tag node must match
  3  @context   Optional context of the next node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;

    ok  $e == $d->an_d_e_b_a;

    ok  $f == $e->an_e;

    ok !$f->an_f;

ap($node, $current, @context)

Return the previous node if the specified $node has the tag specified by $current and the previous node is in the specified @context.

     Parameter  Description
  1  $node      Node
  2  $current   Tag node must match
  3  @context   Optional context of the previous node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;

    ok  $c == $d->ap_d_c_b_a;

    ok  $c == $d->ap_d;

    ok !$c->ap_c;

apn($node, $prev, $current, @context)

Return (previous node, next node) if the $previous and $current nodes have the specified tags and the next node is in the specified @context else return (). The specified @context must have at least one element otherwise () is returned.

     Parameter  Description
  1  $node      Current node
  2  $prev      Tag for the previous node
  3  $current   Tag for specified node
  4  @context   Context for the next node.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;

    is_deeply[$c, $e], [$d->apn_c_d_e_b_a];

matchesFirst($node, @sequence)

Return the specified $node if its children match the specified <@sequence> forwards from the first child else return undef.

     Parameter  Description
  1  $node      Node
  2  @sequence  Sequence.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END
    my ($b, $c, $d, $e, $f) = $a->byList;

    ok   $a->matchesFirst_b_c_d_e_f;
    ok  !$a->matchesFirst_c;
    ok   $a->matchesLast_f_e_d_c_b;
    ok  !$a->matchesLast_f_d;
    ok   $c->matchesNext_d_e_f;
    ok  !$d->matchesNext_e_f_a;
    ok   $e->matchesPrev_d_c_b;
    ok  !$e->matchesPrev_d_c_b_a;
   }

matchesLast($node, @sequence)

Return the specified $node if its children match the specified <@sequence> backwards from the last child else return undef.

     Parameter  Description
  1  $node      Node
  2  @sequence  Sequence.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END
    my ($b, $c, $d, $e, $f) = $a->byList;

    ok   $a->matchesFirst_b_c_d_e_f;
    ok  !$a->matchesFirst_c;
    ok   $a->matchesLast_f_e_d_c_b;
    ok  !$a->matchesLast_f_d;
    ok   $c->matchesNext_d_e_f;
    ok  !$d->matchesNext_e_f_a;
    ok   $e->matchesPrev_d_c_b;
    ok  !$e->matchesPrev_d_c_b_a;
   }

matchesNext($node, @sequence)

Return the specified $node if its following siblings match the specified <@sequence> else return undef.

     Parameter  Description
  1  $node      Node
  2  @sequence  Sequence.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END
    my ($b, $c, $d, $e, $f) = $a->byList;

    ok   $a->matchesFirst_b_c_d_e_f;
    ok  !$a->matchesFirst_c;
    ok   $a->matchesLast_f_e_d_c_b;
    ok  !$a->matchesLast_f_d;
    ok   $c->matchesNext_d_e_f;
    ok  !$d->matchesNext_e_f_a;
    ok   $e->matchesPrev_d_c_b;
    ok  !$e->matchesPrev_d_c_b_a;
   }

matchesPrev($node, @sequence)

Return the specified $node if the siblings before $node match the specified <@sequence> with the first element of @sequence nearest to $node and the last element furthest else return undef.

     Parameter  Description
  1  $node      Node
  2  @sequence  Sequence.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END
    my ($b, $c, $d, $e, $f) = $a->byList;

    ok   $a->matchesFirst_b_c_d_e_f;
    ok  !$a->matchesFirst_c;
    ok   $a->matchesLast_f_e_d_c_b;
    ok  !$a->matchesLast_f_d;
    ok   $c->matchesNext_d_e_f;
    ok  !$d->matchesNext_e_f_a;
    ok   $e->matchesPrev_d_c_b;
    ok  !$e->matchesPrev_d_c_b_a;
   }

Child of, Parent of, Sibling of

Nodes that are directly above, below or adjacent to another node.

parentOf($parent, $child, @context)

Returns the specified $parent node if it is the parent of the specified $child node and the $parent node is in the specified optional context.

     Parameter  Description
  1  $parent    Parent
  2  $child     Child
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END


    ok $e->parentOf($j);                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

childOf($child, $parent, @context)

Returns the specified $child node if it is a child of the specified $parent node and the $child node is in the specified optional context.

     Parameter  Description
  1  $child     Child
  2  $parent    Parent
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END


    ok $j->childOf($e);                                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

succeedingSiblingOf($child, $sibling, @context)

Returns the specified $child node if it has the same parent as $sibling and occurs after $sibling and has the optionally specified context else returns undef.

     Parameter  Description
  1  $child     Child
  2  $sibling   Sibling thought to occur before child
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
    <d/>
    <e/>
   </b>
   <B>
    <C/>
    <D/>
    <E/>
   </B>
  </a>
  END

    my ($c, $d, $e, $b, $C, $D, $B) = $a->byList;

    ok !$e->succeedingSiblingOf($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $e->succeedingSiblingOf($d);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $e->succeedingSiblingOf($c);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$e->succeedingSiblingOf($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$e->succeedingSiblingOf($B);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$e->succeedingSiblingOf($C);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$c->precedingSiblingOf($c);
    ok  $c->precedingSiblingOf($d);
    ok  $c->precedingSiblingOf($e);
    ok !$c->precedingSiblingOf($b);
    ok !$c->precedingSiblingOf($B);
    ok !$c->precedingSiblingOf($C);

precedingSiblingOf($child, $sibling, @context)

Returns the specified $child node if it has the same parent as $sibling and occurs before $sibling and has the optionally specified context else returns undef.

     Parameter  Description
  1  $child     Child
  2  $sibling   Sibling thought to occur after child
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
    <d/>
    <e/>
   </b>
   <B>
    <C/>
    <D/>
    <E/>
   </B>
  </a>
  END

    my ($c, $d, $e, $b, $C, $D, $B) = $a->byList;
    ok !$e->succeedingSiblingOf($e);
    ok  $e->succeedingSiblingOf($d);
    ok  $e->succeedingSiblingOf($c);
    ok !$e->succeedingSiblingOf($b);
    ok !$e->succeedingSiblingOf($B);
    ok !$e->succeedingSiblingOf($C);


    ok !$c->precedingSiblingOf($c);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $c->precedingSiblingOf($d);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $c->precedingSiblingOf($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$c->precedingSiblingOf($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$c->precedingSiblingOf($B);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$c->precedingSiblingOf($C);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Navigation

Move around in the parse tree.

go($node, @path)

Return the node reached from the specified $node via the specified path: (index position?)* where index is the tag of the next node to be chosen and position is the optional zero based position within the index of those tags under the current node. Position defaults to zero if not specified. Position can also be negative to index back from the top of the index array. * can be used as the last position to retrieve all nodes with the final tag.

     Parameter  Description
  1  $node      Node
  2  @path      Search specification.

Example:

    my $x = Data::Edit::Xml::new(my $s = <<END);
  <aa>
    <a>
      <b/>
        <c id="1"/><c id="2"/><c id="3"/><c id="4"/>
      <d/>
    </a>
  </aa>
  END


    ok $x->go(qw(a c))   ->id == 1;                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x->go(qw(a c -2))->id == 3;                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x->go(qw(a c *)) == 4;                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok 1234 == join '', map {$_->id} $x->go(qw(a c *));                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

c($node, $tag)

Return an array of all the nodes with the specified tag below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>

    <b id="b1"><c id="1"/></b>  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    <d id="d1"><c id="2"/></d>  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    <e id="e1"><c id="3"/></e>  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    <b id="b2"><c id="4"/></b>  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    <d id="d2"><c id="5"/></d>  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    <e id="e2"><c id="6"/></e>  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  </a>
  END


    is_deeply [map{$_->id} $x->c(q(d))],  [qw(d1 d2)];                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

cText($node)

Return an array of all the text nodes immediately below the specified $node.

     Parameter  Description
  1  $node      Node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>b1
      <c/>
      b2
      <d/>
      b3
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my (undef, $c, undef, $d, undef, $b, $f, $e) = $a->byList;
    is_deeply ["b".."f"], [map {-t $_} ($b, $c, $d, $e, $f)];


    ok  $b->cText == 3;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    my @b = $b->cText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok "b1 b2 b3" eq join " ", map {trim $_->text} @b;

    ok !$e->cText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$a->cText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

findById($node, $id)

Find a node in the parse tree under the specified $node with the specified $id.

     Parameter  Description
  1  $node      Parse tree
  2  $id        Id desired.

Example:

    ok -p $a eq <<END;
  <a id="i1">
    <b id="i2"/>
    <c id="i3"/>
    <B id="i4">
      <c id="i5"/>
    </B>
    <c id="i6"/>
    <b id="i7"/>
  </a>
  END

    ok -t $a->findById_i4 eq q(B);

    ok -t $a->findById_i5 eq q(c);

matchesNode($first, $second, @attributes)

Return the $first node if it matches the $second node's tag and the specified @attributes else return undef.

     Parameter    Description
  1  $first       First node
  2  $second      Second node
  3  @attributes  Attributes to match on

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a       id="1">
    <b     id="2"   name="b">
      <c   id="3"   name="c"/>
    </b>
    <c     id="4">
      <b   id="5"   name="b">
        <c id="6"   name="c"/>
      </b>
    </c>
  </a>
  END

    my ($c, $b, $C, $B) = $a->byList;
    ok  $b->id == 2;
    ok  $c->id == 3;
    ok  $B->id == 5;
    ok  $C->id == 6;

    ok  $c->matchesNode($C, qw(name));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$c->matchesNode($C, qw(id name));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok  $c->matchesSubTree($C, qw(name));
    ok  $b->matchesSubTree($B, qw(name));
    ok !$c->matchesSubTree($C, qw(id name));
    ok !$b->matchesSubTree($C, qw(name));

    is_deeply [$a->findMatchingSubTrees($b, qw(name))], [$b, $B];
    is_deeply [$a->findMatchingSubTrees($c, qw(name))], [$c, $C];
    is_deeply [$a->findMatchingSubTrees(new(q(<c/>)))], [$c, $C];
    is_deeply [$a->findMatchingSubTrees(new(q(<b><c/></b>)))], [$b, $B];
    is_deeply [$a->findMatchingSubTrees(new(q(<b id="2"><c id="3"/></b>)), q(id))], [$b];
   }

matchesSubTree($first, $second, @attributes)

Return the $first node if it matches the $second node and the nodes under the first node match the corresponding nodes under the second node, else return undef.

     Parameter    Description
  1  $first       First node
  2  $second      Second node
  3  @attributes  Attributes to match on

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a       id="1">
    <b     id="2"   name="b">
      <c   id="3"   name="c"/>
    </b>
    <c     id="4">
      <b   id="5"   name="b">
        <c id="6"   name="c"/>
      </b>
    </c>
  </a>
  END

    my ($c, $b, $C, $B) = $a->byList;
    ok  $b->id == 2;
    ok  $c->id == 3;
    ok  $B->id == 5;
    ok  $C->id == 6;
    ok  $c->matchesNode($C, qw(name));
    ok !$c->matchesNode($C, qw(id name));

    ok  $c->matchesSubTree($C, qw(name));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $b->matchesSubTree($B, qw(name));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$c->matchesSubTree($C, qw(id name));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$b->matchesSubTree($C, qw(name));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$a->findMatchingSubTrees($b, qw(name))], [$b, $B];
    is_deeply [$a->findMatchingSubTrees($c, qw(name))], [$c, $C];
    is_deeply [$a->findMatchingSubTrees(new(q(<c/>)))], [$c, $C];
    is_deeply [$a->findMatchingSubTrees(new(q(<b><c/></b>)))], [$b, $B];
    is_deeply [$a->findMatchingSubTrees(new(q(<b id="2"><c id="3"/></b>)), q(id))], [$b];
   }

findMatchingSubTrees($node, $subTree, @attributes)

Find nodes in the parse tree whose sub tree matches the specified $subTree excluding any of the specified $attributes.

     Parameter    Description
  1  $node        Parse tree
  2  $subTree     Parse tree to match
  3  @attributes  Attributes to match on

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a       id="1">
    <b     id="2"   name="b">
      <c   id="3"   name="c"/>
    </b>
    <c     id="4">
      <b   id="5"   name="b">
        <c id="6"   name="c"/>
      </b>
    </c>
  </a>
  END

    my ($c, $b, $C, $B) = $a->byList;
    ok  $b->id == 2;
    ok  $c->id == 3;
    ok  $B->id == 5;
    ok  $C->id == 6;
    ok  $c->matchesNode($C, qw(name));
    ok !$c->matchesNode($C, qw(id name));
    ok  $c->matchesSubTree($C, qw(name));
    ok  $b->matchesSubTree($B, qw(name));
    ok !$c->matchesSubTree($C, qw(id name));
    ok !$b->matchesSubTree($C, qw(name));


    is_deeply [$a->findMatchingSubTrees($b, qw(name))], [$b, $B];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$a->findMatchingSubTrees($c, qw(name))], [$c, $C];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$a->findMatchingSubTrees(new(q(<c/>)))], [$c, $C];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$a->findMatchingSubTrees(new(q(<b><c/></b>)))], [$b, $B];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$a->findMatchingSubTrees(new(q(<b id="2"><c id="3"/></b>)), q(id))], [$b];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }

First

Find nodes that are first amongst their siblings.

first($node, @context)

Return the first node below the specified $node optionally checking the first node's context. See addFirst to ensure that an expected node is in position.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Use firstNonBlank to skip a (rare) initial blank text CDATA. Use firstNonBlankX to die rather then receive a returned undef or false result.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


    ok  $a->go(q(b))->first->id == 13;                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a->go(q(b))->first(qw(c b a));                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->go(q(b))->first(qw(b a));                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstn($node, $N, @context)

Return the $n'th first node below the specified $node optionally checking its context or undef if there is no such node. firstn(1) is identical in effect to first.

     Parameter  Description
  1  $node      Node
  2  $N         Number of times to go first
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d/><e/><f/></c></b></a>
  END
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
        <e/>
        <f/>
      </c>
    </b>
  </a>
  END
    ok  -t $a->firstn_0 eq q(a);
    ok  -t $a->firstn_1 eq q(b);
    ok  -t $a->firstn_2 eq q(c);
    ok  -t $a->firstn_3 eq q(d);

    ok  -t $a->firstn_3__nextn_0 eq q(d);
    ok  -t $a->firstn_3__nextn_1 eq q(e);
    ok  -t $a->firstn_3__nextn_2 eq q(f);
   }

firstText($node, @context)

Return the first node under the specified $node if it is in the optional and it is a text node otherwise undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new("<a>AA<b/>BB<c/>CC<d/><e/><f/>DD<g/>HH</a>");
    ok -p $a eq <<END;
  <a>AA
    <b/>
  BB
    <c/>
  CC
    <d/>
    <e/>
    <f/>
  DD
    <g/>
  HH
  </a>
  END
    ok  $a->firstText_a__text eq q(AA);
    ok !$a->go_c__firstText_c_a;
    ok !$a->go_c__firstText_c_b;
    ok  $a->lastText__text eq q(HH);
    ok  $a->lastText_a__text eq q(HH);
    ok !$a->go_c__lastText;
    ok  $a->go_c__nextText_c_a__text eq q(CC);
    ok !$a->go_e__nextText;
    ok  $a->go_c__prevText_c__text eq q(BB);
    ok !$a->go_e__prevText;

firstTextMatches($node, $match, @context)

Return the first node under the specified $node if: it is a text mode; its text matches the specified regular expression; the specified $node is in the optional specified context. Else return undef.

     Parameter  Description
  1  $node      Node
  2  $match     Regular expression the text must match
  3  @context   Optional context of specified node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb<c>cc</c>BB
    </b>
  </a>
  END

    my ($bb, $cc, $c, $BB, $b) = $a->byList;

    ok $bb->matchesText(qr(bb));


    ok $b->at_b_a &&  $b->firstTextMatches(qr(bb));                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok                $b->firstTextMatches(qr(bb), qw(b a));                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $c->at_c_b &&  $c->firstTextMatches(qr(cc));                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $c->at_c_b && !$c->firstTextMatches(qr(bb));                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstBy($node, @tags)

Return a list of the first instance of each specified tag encountered in a post-order traversal from the specified $node or a hash of all first instances if no tags are specified.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


     {my %f = $a->firstBy;                                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok $f{b}->id == 12;

firstDown($node, @tags)

Return a list of the first instance of each specified tag encountered in a pre-order traversal from the specified $node or a hash of all first instances if no tags are specified.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

     {my %f = $a->firstDown;                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok $f{b}->id == 15;

firstIn($node, @tags)

Return the first child node matching one of the named tags under the specified parent node.

     Parameter  Description
  1  $node      Parent node
  2  @tags      Child tags to search for.

Example:

    ok $a->prettyStringCDATA eq <<'END';
  <a><CDATA> </CDATA>
      <A/>
  <CDATA>  </CDATA>
      <C/>
  <CDATA>  </CDATA>
      <E/>
  <CDATA>  </CDATA>
      <G/>
  <CDATA>  </CDATA>
  </a>
  END


    ok $a->firstIn(qw(b B c C))->tag eq qq(C);                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstNot($node, @tags)

Return the first child node that does not match any of the named @tags under the specified parent $node. Return undef if there is no such child node.

     Parameter  Description
  1  $node      Parent node
  2  @tags      Child tags to avoid.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;

    ok $c == $a->firstNot_a_b;

firstInIndex($node, @context)

Return the specified $node if it is first in its index and optionally at the specified context else undef

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END


    ok  $a->findByNumber (5)->firstInIndex;                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->findByNumber(7) ->firstInIndex;                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstOf($node, @tags)

Return an array of the nodes that are continuously first under their specified parent node and that match the specified list of tags.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/><d/><d/><e/><d/><d/><c/></b></a>
  END


    is_deeply [qw(c d d)], [map {-t $_} $a->go(q(b))->firstOf(qw(c d))];            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstWhile($node, @tags)

Go first from the specified $node and continue deeper firstly as long as each first child node matches one of the specified @tags. Return the deepest such node encountered or else return undef if no such node is encountered.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e>
            <f/>
          </e>
        </d>
      </c>
    </b>
    <B>
      <C>
        <D>
          <E>
            <F/>
          </E>
        </D>
      </C>
    </B>
  </a>
  END
    my ($f, $e, $d, $c, $b, $F, $E, $D, $C, $B) = $a->byList;

    ok eval qq(-t \$$_ eq q($_)), $_ for qw(a b c d e f B C D E F);

    ok  $d == $a->firstWhile_a_d_c_b;
    ok  $f == $a->firstWhile_a_d_c_b_e_f_g_h;
    ok !$b->firstWhile_a;

    ok  $e == $a->firstUntil_e_d;
    ok       !$c->firstUntil_c;
    ok       !$b->firstUntil_a;

    ok  $D == $a->lastWhile_a_D_C_B;
    ok  $F == $a->lastWhile_a_D_C_B_E_F_G_H;
    ok !$B->lastWhile_a;

    ok  $E == $a->lastUntil_E_D;
    ok       !$C->lastUntil_C;
    ok !$B->lastUntil_a;

firstUntil($node, @context)

Go first from the specified $node and continue deeper firstly until a first child node matches the specified @context or return undef if there is no such node. Return the first child of the specified $node if no @context is specified.

     Parameter  Description
  1  $node      Node
  2  @context   Context to search for.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e>
            <f/>
          </e>
        </d>
      </c>
    </b>
    <B>
      <C>
        <D>
          <E>
            <F/>
          </E>
        </D>
      </C>
    </B>
  </a>
  END
    my ($f, $e, $d, $c, $b, $F, $E, $D, $C, $B) = $a->byList;

    ok eval qq(-t \$$_ eq q($_)), $_ for qw(a b c d e f B C D E F);

    ok  $d == $a->firstWhile_a_d_c_b;
    ok  $f == $a->firstWhile_a_d_c_b_e_f_g_h;
    ok !$b->firstWhile_a;

    ok  $e == $a->firstUntil_e_d;
    ok       !$c->firstUntil_c;
    ok       !$b->firstUntil_a;

    ok  $D == $a->lastWhile_a_D_C_B;
    ok  $F == $a->lastWhile_a_D_C_B_E_F_G_H;
    ok !$B->lastWhile_a;

    ok  $E == $a->lastUntil_E_D;
    ok       !$C->lastUntil_C;
    ok !$B->lastUntil_a;

firstUntilText($node, @context)

Go first from the specified $node and continue deeper firstly until a text node is encountered whose parent matches the specified @context or return undef if there is no such node.

     Parameter  Description
  1  $node      Node
  2  @context   Context to search for.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      cccc
      <d/>
      <e/>
    </b>
    <f>
      <g/>
      hhhh
      <i/>
    </f>
    <j>
      <k/>
      <l/>
      mmmm
    </j>
  </a>
  END


    ok $a->firstUntilText->text =~ m(cccc)s;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $a->lastUntilText ->text =~ m(mmmm)s;

firstContextOf($node, @context)

Return the first node encountered in the specified context in a depth first post-order traversal of the parse tree.

     Parameter  Description
  1  $node      Node
  2  @context   Array of tags specifying context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a        id="a1">
    <b1     id="b1">
       <c   id="c1">
         <d id="d1">DD11</d>
         <e id="e1">EE11</e>
      </c>
    </b1>
    <b2     id="b2">
       <c   id="c2">
         <d id="d2">DD22</d>
         <e id="e2">EE22</e>
      </c>
    </b2>
    <b3     id="b3">
       <c   id="c3">
         <d id="d3">DD33</d>
         <e id="e3">EE33</e>
      </c>
    </b3>
  </a>
  END


    ok $x->firstContextOf(qw(d c))         ->id     eq qq(d1);                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x->firstContextOf(qw(e c b2))      ->id     eq qq(e2);                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x->firstContextOf(qw(CDATA d c b2))->string eq qq(DD22);                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstSibling($node, @context)

Return the first sibling of the specified $node in the optional @context else undef

     Parameter  Description
  1  $node      Node
  2  @context   Array of tags specifying context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


    ok  $a->go(qw(b b))->firstSibling->id == 13;                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Last

Find nodes that are last amongst their siblings.

last($node, @context)

Return the last node below the specified $node optionally checking the last node's context. See addLast to ensure that an expected node is in position.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Use lastNonBlank to skip a (rare) initial blank text CDATA. Use lastNonBlankX to die rather then receive a returned undef or false result.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


    ok  $a->go(q(b))->last ->id == 22;                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a->go(q(b))->last(qw(g b a));                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->go(q(b))->last(qw(b a));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->go(q(b))->last(qw(b a));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastn($node, $N, @context)

Return the $n'th last node below the specified $node optionally checking its context or undef if there is no such node. lastn(1) is identical in effect to last.

     Parameter  Description
  1  $node      Node
  2  $N         Number of times to go last
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d/><e/><f/></c></b>
     <B><C><D/><E/><F/></C></B></a>
  END
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
        <e/>
        <f/>
      </c>
    </b>
    <B>
      <C>
        <D/>
        <E/>
        <F/>
      </C>
    </B>
  </a>
  END

    ok  -t $a->lastn_0 eq q(a);
    ok  -t $a->lastn_1 eq q(B);
    ok  -t $a->lastn_2 eq q(C);
    ok  -t $a->lastn_3 eq q(F);

    ok  -t $a->lastn_3__prevn_0 eq q(F);
    ok  -t $a->lastn_3__prevn_1 eq q(E);
    ok  -t $a->lastn_3__prevn_2 eq q(D);
   }

lastText($node, @context)

Return the last node under the specified $node if it is in the optional and it is a text node otherwise undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new("<a>AA<b/>BB<c/>CC<d/><e/><f/>DD<g/>HH</a>");
    ok -p $a eq <<END;
  <a>AA
    <b/>
  BB
    <c/>
  CC
    <d/>
    <e/>
    <f/>
  DD
    <g/>
  HH
  </a>
  END
    ok  $a->firstText_a__text eq q(AA);
    ok !$a->go_c__firstText_c_a;
    ok !$a->go_c__firstText_c_b;
    ok  $a->lastText__text eq q(HH);
    ok  $a->lastText_a__text eq q(HH);
    ok !$a->go_c__lastText;
    ok  $a->go_c__nextText_c_a__text eq q(CC);
    ok !$a->go_e__nextText;
    ok  $a->go_c__prevText_c__text eq q(BB);
    ok !$a->go_e__prevText;

lastTextMatches($node, $match, @context)

Return the last node under the specified $node if: it is a text mode; its text matches the specified regular expression; the specified $node is in the optional specified context. Else return undef.

     Parameter  Description
  1  $node      Node
  2  $match     Regular expression the text must match
  3  @context   Optional context of specified  node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb<c>cc</c>BB
    </b>
  </a>
  END

    my ($bb, $cc, $c, $BB, $b) = $a->byList;

    ok $BB->matchesText(qr(BB));


    ok $b->at_b_a &&  $b->lastTextMatches(qr(BB));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok                $b->lastTextMatches(qr(BB), qw(b a));                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $c->at_c_b &&  $c->lastTextMatches(qr(cc));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $c->at_c_b && !$c->lastTextMatches(qr(bb));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastBy($node, @tags)

Return a list of the last instance of each specified tag encountered in a post-order traversal from the specified $node or a hash of all last instances if no tags are specified.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


     {my %l = $a->lastBy;                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok $l{b}->id == 23;

lastDown($node, @tags)

Return a list of the last instance of each specified tag encountered in a pre-order traversal from the specified $node or a hash of all last instances if no tags are specified.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

     {my %l = $a->lastDown;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok $l{b}->id == 26;

lastIn($node, @tags)

Return the last child node matching one of the named tags under the specified parent node.

     Parameter  Description
  1  $node      Parent node
  2  @tags      Child tags to search for.

Example:

    ok $a->prettyStringCDATA eq <<'END';
  <a><CDATA> </CDATA>
      <A/>
  <CDATA>  </CDATA>
      <C/>
  <CDATA>  </CDATA>
      <E/>
  <CDATA>  </CDATA>
      <G/>
  <CDATA>  </CDATA>
  </a>
  END


    ok $a->lastIn(qw(e E f F))->tag eq qq(E);                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastNot($node, @tags)

Return the last child node that does not match any of the named @tags under the specified parent $node. Return undef if there is no such child node.

     Parameter  Description
  1  $node      Parent node
  2  @tags      Child tags to avoid.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;

    ok $d == $a->lastNot_e_f;

lastOf($node, @tags)

Return an array of the nodes that are continuously last under their specified parent node and that match the specified list of tags.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/><d/><d/><e/><d/><d/><c/></b></a>
  END


    is_deeply [qw(d d c)], [map {-t $_} $a->go(q(b))->lastOf (qw(c d))];            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastInIndex($node, @context)

Return the specified $node if it is last in its index and optionally at the specified context else undef

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END


    ok  $a->findByNumber(10)->lastInIndex;                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->findByNumber(7) ->lastInIndex;                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastContextOf($node, @context)

Return the last node encountered in the specified context in a depth first reverse pre-order traversal of the parse tree.

     Parameter  Description
  1  $node      Node
  2  @context   Array of tags specifying context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a        id="a1">
    <b1     id="b1">
       <c   id="c1">
         <d id="d1">DD11</d>
         <e id="e1">EE11</e>
      </c>
    </b1>
    <b2     id="b2">
       <c   id="c2">
         <d id="d2">DD22</d>
         <e id="e2">EE22</e>
      </c>
    </b2>
    <b3     id="b3">
       <c   id="c3">
         <d id="d3">DD33</d>
         <e id="e3">EE33</e>
      </c>
    </b3>
  </a>
  END


    ok $x-> lastContextOf(qw(d c))         ->id     eq qq(d3);                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x-> lastContextOf(qw(e c b2     )) ->id     eq qq(e2);                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $x-> lastContextOf(qw(CDATA e c b2))->string eq qq(EE22);                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastSibling($node, @context)

Return the last sibling of the specified $node in the optional @context else undef

     Parameter  Description
  1  $node      Node
  2  @context   Array of tags specifying context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


    ok  $a->go(qw(b b))->lastSibling ->id == 22;                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastWhile($node, @tags)

Go last from the specified $node and continue deeper lastly as long as each last child node matches one of the specified @tags. Return the deepest such node encountered or else return undef if no such node is encountered.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e>
            <f/>
          </e>
        </d>
      </c>
    </b>
    <B>
      <C>
        <D>
          <E>
            <F/>
          </E>
        </D>
      </C>
    </B>
  </a>
  END
    my ($f, $e, $d, $c, $b, $F, $E, $D, $C, $B) = $a->byList;

    ok eval qq(-t \$$_ eq q($_)), $_ for qw(a b c d e f B C D E F);

    ok  $d == $a->firstWhile_a_d_c_b;
    ok  $f == $a->firstWhile_a_d_c_b_e_f_g_h;
    ok !$b->firstWhile_a;

    ok  $e == $a->firstUntil_e_d;
    ok       !$c->firstUntil_c;
    ok       !$b->firstUntil_a;

    ok  $D == $a->lastWhile_a_D_C_B;
    ok  $F == $a->lastWhile_a_D_C_B_E_F_G_H;
    ok !$B->lastWhile_a;

    ok  $E == $a->lastUntil_E_D;
    ok       !$C->lastUntil_C;
    ok !$B->lastUntil_a;

lastUntil($node, @context)

Go last from the specified $node and continue deeper lastly until a last child node matches the specified @context or return undef if there is no such node. Return the last child of the specified $node if no @context is specified.

     Parameter  Description
  1  $node      Node
  2  @context   Context to search for.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e>
            <f/>
          </e>
        </d>
      </c>
    </b>
    <B>
      <C>
        <D>
          <E>
            <F/>
          </E>
        </D>
      </C>
    </B>
  </a>
  END
    my ($f, $e, $d, $c, $b, $F, $E, $D, $C, $B) = $a->byList;

    ok eval qq(-t \$$_ eq q($_)), $_ for qw(a b c d e f B C D E F);

    ok  $d == $a->firstWhile_a_d_c_b;
    ok  $f == $a->firstWhile_a_d_c_b_e_f_g_h;
    ok !$b->firstWhile_a;

    ok  $e == $a->firstUntil_e_d;
    ok       !$c->firstUntil_c;
    ok       !$b->firstUntil_a;

    ok  $D == $a->lastWhile_a_D_C_B;
    ok  $F == $a->lastWhile_a_D_C_B_E_F_G_H;
    ok !$B->lastWhile_a;

    ok  $E == $a->lastUntil_E_D;
    ok       !$C->lastUntil_C;
    ok !$B->lastUntil_a;

lastUntilText($node, @context)

Go last from the specified $node and continue deeper lastly until a last child text node matches the specified @context or return undef if there is no such node.

     Parameter  Description
  1  $node      Node
  2  @context   Context to search for.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      cccc
      <d/>
      <e/>
    </b>
    <f>
      <g/>
      hhhh
      <i/>
    </f>
    <j>
      <k/>
      <l/>
      mmmm
    </j>
  </a>
  END

    ok $a->firstUntilText->text =~ m(cccc)s;

    ok $a->lastUntilText ->text =~ m(mmmm)s;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Next

Find sibling nodes after the specified $node.

next($node, @context)

Return the node next to the specified $node, optionally checking the next node's context. See addNext to ensure that an expected node is in position.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Use nextNonBlank to skip a (rare) initial blank text CDATA. Use nextNonBlankX to die rather then receive a returned undef or false result.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


    ok  $a->go(qw(b b e))->next ->id == 19;                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a->go(qw(b b e))->next(qw(f b b a));                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->go(qw(b b e))->next(qw(f b a));                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

nextn($node, $N, @context)

Return the $n'th next node after the specified $node optionally checking its context or undef if there is no such node. nextn(1) is identical in effect to next.

     Parameter  Description
  1  $node      Node
  2  $N         Number of times to go next
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d/><e/><f/></c></b></a>
  END
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
        <e/>
        <f/>
      </c>
    </b>
  </a>
  END
    ok  -t $a->firstn_0 eq q(a);
    ok  -t $a->firstn_1 eq q(b);
    ok  -t $a->firstn_2 eq q(c);
    ok  -t $a->firstn_3 eq q(d);

    ok  -t $a->firstn_3__nextn_0 eq q(d);
    ok  -t $a->firstn_3__nextn_1 eq q(e);
    ok  -t $a->firstn_3__nextn_2 eq q(f);
   }

nextText($node, @context)

Return the node after the specified $node if it is in the optional and it is a text node otherwise undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new("<a>AA<b/>BB<c/>CC<d/><e/><f/>DD<g/>HH</a>");
    ok -p $a eq <<END;
  <a>AA
    <b/>
  BB
    <c/>
  CC
    <d/>
    <e/>
    <f/>
  DD
    <g/>
  HH
  </a>
  END
    ok  $a->firstText_a__text eq q(AA);
    ok !$a->go_c__firstText_c_a;
    ok !$a->go_c__firstText_c_b;
    ok  $a->lastText__text eq q(HH);
    ok  $a->lastText_a__text eq q(HH);
    ok !$a->go_c__lastText;
    ok  $a->go_c__nextText_c_a__text eq q(CC);
    ok !$a->go_e__nextText;
    ok  $a->go_c__prevText_c__text eq q(BB);
    ok !$a->go_e__prevText;

nextTextMatches($node, $match, @context)

Return the next node to the specified $node if: it is a text mode; its text matches the specified regular expression; the specified $node is in the optional specified context. Else return undef.

     Parameter  Description
  1  $node      Node
  2  $match     Regular expression the text must match
  3  @context   Optional context of specified node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb<c>cc</c>BB
    </b>
  </a>
  END

    ok $cc->matchesText(qr(cc));


    ok $c->at_c_b &&  $c->nextTextMatches(qr(BB));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b->at_b   && !$b->nextTextMatches(qr(BB));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

nextIn($node, @tags)

Return the nearest sibling after the specified $node that matches one of the named tags or undef if there is no such sibling node.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

    ok $a->prettyStringCDATA eq <<'END';
  <a><CDATA> </CDATA>
      <A/>
  <CDATA>  </CDATA>
      <C/>
  <CDATA>  </CDATA>
      <E/>
  <CDATA>  </CDATA>
      <G/>
  <CDATA>  </CDATA>
  </a>
  END


    ok $a->firstIn(qw(b B c C))->nextIn(qw(A G))->tag eq qq(G);                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

nextOn($node, @tags)

Step forwards as far as possible from the specified $node while remaining on nodes with the specified tags. In scalar context return the last such node reached or the starting node if no such steps are possible. In array context return the start node and any following matching nodes.

     Parameter  Description
  1  $node      Start node
  2  @tags      Tags identifying nodes that can be step on to context.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="1"/>
      <d id="2"/>
      <c id="3"/>
      <d id="4"/>
      <e id="5"/>
    </b>
  </a>
  END

    ok $c->id == 1;

    ok $e->id == 5;


    ok $c->nextOn(qw(d))  ->id == 2;                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $c->nextOn(qw(c d))->id == 4;                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $e->nextOn(qw(c d))     == $e;                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

nextWhile($node, @tags)

Go to the next sibling of the specified $node and continue forwards while the tag of each sibling node matches one of the specified @tags. Return the first sibling node that does not match else undef if there is no such sibling.

     Parameter  Description
  1  $node      Node
  2  @tags      Child tags to avoid.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;

    ok $e == $b->nextWhile_c_d;


    ok $c == $b->nextWhile;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

nextUntil($node, @tags)

Go to the next sibling of the specified $node and continue forwards until the tag of a sibling node matches one of the specified @tags. Return the matching sibling node else undef if there is no such sibling node.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to look for.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;

    ok $e == $b->nextUntil_e_f;


    ok      !$b->nextUntil;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Prev

Find sibling nodes before the specified $node.

prev($node, @context)

Return the node before the specified $node, optionally checking the previous node's context. See addLast to ensure that an expected node is in position.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Use prevNonBlank to skip a (rare) initial blank text CDATA. Use prevNonBlankX to die rather then receive a returned undef or false result.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END


    ok  $a->go(qw(b b e))->prev ->id == 17;                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a->go(qw(b b e))->prev(qw(d b b a));                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$a->go(qw(b b e))->prev(qw(d b a));                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

prevText($node, @context)

Return the node before the specified $node if it is in the optional and it is a text node otherwise undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new("<a>AA<b/>BB<c/>CC<d/><e/><f/>DD<g/>HH</a>");
    ok -p $a eq <<END;
  <a>AA
    <b/>
  BB
    <c/>
  CC
    <d/>
    <e/>
    <f/>
  DD
    <g/>
  HH
  </a>
  END
    ok  $a->firstText_a__text eq q(AA);
    ok !$a->go_c__firstText_c_a;
    ok !$a->go_c__firstText_c_b;
    ok  $a->lastText__text eq q(HH);
    ok  $a->lastText_a__text eq q(HH);
    ok !$a->go_c__lastText;
    ok  $a->go_c__nextText_c_a__text eq q(CC);
    ok !$a->go_e__nextText;
    ok  $a->go_c__prevText_c__text eq q(BB);
    ok !$a->go_e__prevText;

prevn($node, $N, @context)

Return the $n'th previous node after the specified $node optionally checking its context or undef if there is no such node. prevn(1) is identical in effect to prev.

     Parameter  Description
  1  $node      Node
  2  $N         Number of times to go prev
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d/><e/><f/></c></b>
     <B><C><D/><E/><F/></C></B></a>
  END
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
        <e/>
        <f/>
      </c>
    </b>
    <B>
      <C>
        <D/>
        <E/>
        <F/>
      </C>
    </B>
  </a>
  END

    ok  -t $a->lastn_0 eq q(a);
    ok  -t $a->lastn_1 eq q(B);
    ok  -t $a->lastn_2 eq q(C);
    ok  -t $a->lastn_3 eq q(F);

    ok  -t $a->lastn_3__prevn_0 eq q(F);
    ok  -t $a->lastn_3__prevn_1 eq q(E);
    ok  -t $a->lastn_3__prevn_2 eq q(D);
   }

prevTextMatches($node, $match, @context)

Return the previous node to the specified $node if: it is a text mode; its text matches the specified regular expression; the specified $node is in the optional specified context. Else return undef.

     Parameter  Description
  1  $node      Node
  2  $match     Regular expression the text must match
  3  @context   Optional context of specified node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb<c>cc</c>BB
    </b>
  </a>
  END

    ok $cc->matchesText(qr(cc));


    ok $c->at_c_b &&  $c->prevTextMatches(qr(bb));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b->at_b   && !$b->prevTextMatches(qr(bb));                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

prevIn($node, @tags)

Return the nearest sibling node before the specified $node which matches one of the named tags or undef if there is no such sibling node.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to search for.

Example:

    ok $a->prettyStringCDATA eq <<'END';
  <a><CDATA> </CDATA>
      <A/>
  <CDATA>  </CDATA>
      <C/>
  <CDATA>  </CDATA>
      <E/>
  <CDATA>  </CDATA>
      <G/>
  <CDATA>  </CDATA>
  </a>
  END


    ok $a->lastIn(qw(e E f F))->prevIn(qw(A G))->tag eq qq(A);                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

prevOn($node, @tags)

Step backwards as far as possible while remaining on nodes with the specified tags. In scalar context return the last such node reached or the starting node if no such steps are possible. In array context return the start node and any preceding matching nodes.

     Parameter  Description
  1  $node      Start node
  2  @tags      Tags identifying nodes that can be step on to context.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="1"/>
      <d id="2"/>
      <c id="3"/>
      <d id="4"/>
      <e id="5"/>
    </b>
  </a>
  END

    ok $c->id == 1;

    ok $e->id == 5;


    ok $e->prevOn(qw(d))  ->id == 4;                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $e->prevOn(qw(c d))     == $c;                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

prevWhile($node, @tags)

Go to the previous sibling of the specified $node and continue backwards while the tag of each sibling node matches one of the specified @tags. Return the first sibling node that does not match else undef if there is no such sibling.

     Parameter  Description
  1  $node      Parent node
  2  @tags      Child tags to avoid.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;

    ok $c == $f->prevWhile_e_d;


    ok $b == $c->prevWhile;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

prevUntil($node, @tags)

Go to the previous sibling of the specified $node and continue backwards until the tag of a sibling node matches one of the specified @tags. Return the matching sibling node else undef if there is no such sibling node.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags to look for.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;

    ok $b == $f->prevUntil_a_b;


    ok      !$c->prevUntil;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Up

Methods for moving up the parse tree from a node.

top($node, @context)

Return the top of the parse tree containing the current $node after optionally checking that the $node is in the optional @context.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d/></c></b></a>
  END

    $a->by(sub
     {ok $a == $_->root;

      ok $a == $_->top;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     });

up($node, @context)

Return the parent of the current node optionally checking the parent node's context or return undef if the specified $node is the root of the parse tree. See addWrapWith to ensure that an expected node is in position.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context of parent.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><b><b><b><b><c/></b></b></b></b></c></b></a>
  END

    $a->numberTree;
    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <b id="4">
          <b id="5">
            <b id="6">
              <b id="7">
                <c id="8"/>
              </b>
            </b>
          </b>
        </b>
      </c>
    </b>
  </a>
  END

    my $c = $a->findByNumber(8);
    ok -t $c eq q(c);
    ok  $c->up_b__number == 7;
    ok  $c->upn_2__number == 6;
    ok  $c->upWhile_b__number == 4;
    ok  $c->upWhile_a_b__number == 4;
    ok  $c->upWhile_b_c__number == 2;

    ok  $c->upUntil__number == 8;
    ok  $c->upUntil_b_c__number == 4;
   }

upn($node, $levels, @context)

Go up the specified number of levels from the specified $node and return the node reached optionally checking the parent node's context or undef if there is no such node.upn(1) is identical in effect to up. Or use ancestry to get the path back to the root node.

     Parameter  Description
  1  $node      Start node
  2  $levels    Number of levels to go up
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><b><b><b><b><c/></b></b></b></b></c></b></a>
  END

    $a->numberTree;
    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <b id="4">
          <b id="5">
            <b id="6">
              <b id="7">
                <c id="8"/>
              </b>
            </b>
          </b>
        </b>
      </c>
    </b>
  </a>
  END

    my $c = $a->findByNumber(8);
    ok -t $c eq q(c);
    ok  $c->up_b__number == 7;
    ok  $c->upn_2__number == 6;
    ok  $c->upWhile_b__number == 4;
    ok  $c->upWhile_a_b__number == 4;
    ok  $c->upWhile_b_c__number == 2;

    ok  $c->upUntil__number == 8;
    ok  $c->upUntil_b_c__number == 4;
   }

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d><e/></d></c></b></a>
  END

    my ($e, $d, $c, $b) = $a->byList;

    ok $e = $e->upn_0_e_d_c_b_a;
    ok $d = $e->upn_1_d_c_b_a;
    ok $c = $e->upn_2_c_b_a;
    ok $b = $e->upn_3_b_a;
    ok $a = $e->upn_4_a;
    ok     !$e->upn_5;

    is_deeply [$e, $d, $c, $b, $a], [$e->ancestry];
   }

   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><d><e/></d></c></b></a>
  END

    my ($e, $d, $c, $b) = $a->byList;

    ok $e = $e->upn_0_e_d_c_b_a;

    ok $d = $e->upn_1_d_c_b_a;

    ok $c = $e->upn_2_c_b_a;

    ok $b = $e->upn_3_b_a;

    ok $a = $e->upn_4_a;

    ok     !$e->upn_5;

upWhile($node, @tags)

Go up one level from the specified $node and then continue up while each node matches on of the specified <@tags>. Return the last matching node or undef if no node matched any of the specified @tags.

     Parameter  Description
  1  $node      Start node
  2  @tags      Tags to match

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><b><b><b><b><c/></b></b></b></b></c></b></a>
  END

    $a->numberTree;
    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <b id="4">
          <b id="5">
            <b id="6">
              <b id="7">
                <c id="8"/>
              </b>
            </b>
          </b>
        </b>
      </c>
    </b>
  </a>
  END

    my $c = $a->findByNumber(8);
    ok -t $c eq q(c);
    ok  $c->up_b__number == 7;
    ok  $c->upn_2__number == 6;
    ok  $c->upWhile_b__number == 4;
    ok  $c->upWhile_a_b__number == 4;
    ok  $c->upWhile_b_c__number == 2;

    ok  $c->upUntil__number == 8;
    ok  $c->upUntil_b_c__number == 4;
   }

upWhileFirst($node, @context)

Move up from the specified $node as long as each node is a first node or return undef if the specified $node is not a first node.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $h == $i->upWhileFirst;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a == $c->upWhileFirst;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->upWhileFirst;                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

upWhileLast($node, @context)

Move up from the specified $node as long as each node is a last node or return undef if the specified $node is not a last node.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $j == $j->upWhileLast;                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $a == $l->upWhileLast;                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->upWhileLast;                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $i == $k->upUntilLast;

upWhileIsOnlyChild($node, @context)

Move up from the specified $node as long as each node is an only child or return undef if the specified $node is not an only child.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $h == $i->upWhileIsOnlyChild;                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $j == $j->upWhileIsOnlyChild;                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->upWhileIsOnlyChild;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

upUntil($node, @context)

Find the first node going up from $node that matches the specified @context. The first such node will be the specified $node if no @context is specified or the specified $node matches the specified @context>.

     Parameter  Description
  1  $node      Start node
  2  @context   Context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c><b><b><b><b><c/></b></b></b></b></c></b></a>
  END

    $a->numberTree;
    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <b id="4">
          <b id="5">
            <b id="6">
              <b id="7">
                <c id="8"/>
              </b>
            </b>
          </b>
        </b>
      </c>
    </b>
  </a>
  END

    my $c = $a->findByNumber(8);
    ok -t $c eq q(c);
    ok  $c->up_b__number == 7;
    ok  $c->upn_2__number == 6;
    ok  $c->upWhile_b__number == 4;
    ok  $c->upWhile_a_b__number == 4;
    ok  $c->upWhile_b_c__number == 2;

    ok  $c->upUntil__number == 8;
    ok  $c->upUntil_b_c__number == 4;
   }

upUntilFirst($node, @context)

Move up from the specified $node until we reach the root or a first node.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $b == $d->upUntilFirst;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

upUntilLast($node, @context)

Move up from the specified $node until we reach the root or a last node.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;

upUntilIsOnlyChild($node, @context)

Move up from the specified $node until we reach the root or another only child.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $i == $k->upUntilIsOnlyChild;                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

upThru($node, @tags)

Go up the specified path from the specified $node returning the node at the top or undef if no such node exists.

     Parameter  Description
  1  $node      Start node
  2  @tags      Tags identifying path.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d>
        <e/>
        <f/>
      </d>
    </b>
  </a>
  END

    my ($c, $e, $f, $d, $b) = $a->byList;

    ok -t $f                eq q(f);


    ok -t $f->upThru        eq q(f);                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok -t $f->upThru(qw(d)) eq q(d);                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok -t eval{$f->upThru(qw(d))->last->prev} eq q(e);                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !  eval{$f->upThru(qw(d b))->next};                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

down

Methods for moving down through the parse tree from a node.

downWhileFirst($node, @context)

Move down from the specified $node as long as each lower node is a first node.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $k == $g->downWhileFirst;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $c == $a->downWhileFirst;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $c == $c->downWhileFirst;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok       !$d->downWhileFirst;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

firstLeaf is a synonym for downWhileFirst.

downWhileLast($node, @context)

Move down from the specified $node as long as each lower node is a last node.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e>
        <j/>
      </e>
      <f/>
    </b>
    <g>
      <h>
        <i>
          <k/>
          <l/>
        </i>
      </h>
    </g>
  </a>
  END

    my ($c, $d, $j, $e, $f, $b, $k, $l, $i, $h, $g) = $a->byList;


    ok  $l == $a->downWhileLast;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $l == $g->downWhileLast;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok       !$d->downWhileLast;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

lastLeaf is a synonym for downWhileLast.

downWhileHasSingleChild($node, @context)

Move down from the specified $node as long as it has a single child else return undef.

     Parameter  Description
  1  $node      Start node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok  $h == $g->downWhileHasSingleChild;                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $h == $h->downWhileHasSingleChild;                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok       !$i->downWhileHasSingleChild;                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Editing

Edit the data in the parse tree and change the structure of the parse tree by wrapping and unwrapping nodes, by replacing nodes, by cutting and pasting nodes, by concatenating nodes, by splitting nodes, by adding new text nodes or swapping nodes.

change($node, $name, @context)

Change the name of the specified $node, optionally confirming that the $node is in a specified context and return the $node.

     Parameter  Description
  1  $node      Node
  2  $name      New name
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new('<a/>');


    $a->change(qq(b));                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $a eq '<b/>';

cc is a synonym for change.

ck is a synonym for change.

changeKids($node, $name, @context)

Change the names of all the immediate children of the specified $node, if they match the optional @context, to the specified $tag and return the $node.

     Parameter  Description
  1  $node      Node
  2  $name      New name
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
    <f>
      <g/>
      <h>
        <i/>
      </h>
    </f>
    <j>
      <k/>
      <l>
        <m/>
      </l>
    </j>
  </a>
  END


    $a->changeKids(q(B), qr(\A(b|j|k|l|m)\Z), q(a));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <B>
      <c/>
      <d/>
      <e/>
    </B>
    <f>
      <g/>
      <h>
        <i/>
      </h>
    </f>
    <B>
      <k/>
      <l>
        <m/>
      </l>
    </B>
  </a>
  END

    $a->go_f__changeKids_F;

    ok -p $a eq <<END;
  <a>
    <B>
      <c/>
      <d/>
      <e/>
    </B>
    <f>
      <F/>
      <F>
        <i/>
      </F>
    </f>
    <B>
      <k/>
      <l>
        <m/>
      </l>
    </B>
  </a>
  END

changeText($node, $rf, $rt, $flags, @context)

Change the content of the specified text $node that matches a regular expression $rf presented as a string to a string $rt in the optional @context and return the specified $node else return undef. For a more efficient non unitary method see editText.

     Parameter  Description
  1  $node      Text node
  2  $rf        From re
  3  $rt        To string
  4  $flags     Re flags
  5  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>abcdcba</a>
  END

changeTextToSpace($node, $re, @context)

Change each instance of the content of the specified text $node that matches a regular expression $re to one space and return the specified $node else return undef.

     Parameter  Description
  1  $node      Text node
  2  $re        Regular expression
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>abcdcba</a>
  END

dupPutNext($tree, @context)

Duplicate the specified $tree in the optional @context, place the new tree next after $tree and return the root of the new tree on success else undef.

     Parameter  Description
  1  $tree      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    $a->first__dupPutNext_b;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    $a->last__dupPutPrev_d;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
    <d>
      <e/>
    </d>
  </a>
  END

r is a synonym for dupPutNext.

dupPutPrev($tree, @context)

Duplicate the specified $tree in the optional @context, place the new tree before $tree and return the root of the new tree on success else undef.

     Parameter  Description
  1  $tree      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    $a->first__dupPutNext_b;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    $a->last__dupPutPrev_d;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
    </d>
    <d>
      <e/>
    </d>
  </a>
  END

dupPutNextN($node, $N, @context)

Duplicate the specified $tree $N times in the optional @context, placing each copy after $tree and return the last new node created on success else undef.

     Parameter  Description
  1  $node      Node
  2  $N         Number of duplications
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END

    $a->go_b__dupPutNextN_2;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END

rN is a synonym for dupPutNextN.

setSelectionStart($node, @context)

Set the selection to start at the specified $node in the optional @context and return the specified $node on success else undef..

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END
    $a->go_b_1__setSelectionStart;
    $a->go_d__setSelectionEnd;
    $a->first__moveSelectionBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_d_e__setSelectionStart;
    $a->go_d_g__setSelectionEnd;
    $a->go_b_c__moveSelectionAfter;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <e/>
      <f/>
      <g/>
    </b>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_b_e__setSelectionStart;
    $a->go_b_f__setSelectionEnd;
    $a->last__moveSelectionFirst;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
    </b>
    <d/>
    <b>
      <e><!-- start --></e>
      <f><!-- end --></f>
      <c/>
    </b>
  </a>
  END

    $a->go_d__setSelectionStart;
    $a->last__setSelectionEnd;
    $a->go_b__moveSelectionLast;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
      <d/>
      <b>
        <e><!-- start --></e>
        <f><!-- end --></f>
        <c/>
      </b>
    </b>
  </a>
  END

ss is a synonym for setSelectionStart.

setSelectionEnd($node, @context)

Set the selection to end at the specified $node in the optional @context and return the specified $node on success else undef..

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END
    $a->go_b_1__setSelectionStart;
    $a->go_d__setSelectionEnd;
    $a->first__moveSelectionBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_d_e__setSelectionStart;
    $a->go_d_g__setSelectionEnd;
    $a->go_b_c__moveSelectionAfter;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <e/>
      <f/>
      <g/>
    </b>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_b_e__setSelectionStart;
    $a->go_b_f__setSelectionEnd;
    $a->last__moveSelectionFirst;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
    </b>
    <d/>
    <b>
      <e><!-- start --></e>
      <f><!-- end --></f>
      <c/>
    </b>
  </a>
  END

    $a->go_d__setSelectionStart;
    $a->last__setSelectionEnd;
    $a->go_b__moveSelectionLast;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
      <d/>
      <b>
        <e><!-- start --></e>
        <f><!-- end --></f>
        <c/>
      </b>
    </b>
  </a>
  END

se is a synonym for setSelectionEnd.

moveSelectionFirst($node, @context)

Move the current selection (if there is one) so that it is first under the specified $node in the optional @context and return the specified $node on success else undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END
    $a->go_b_1__setSelectionStart;
    $a->go_d__setSelectionEnd;
    $a->first__moveSelectionBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_d_e__setSelectionStart;
    $a->go_d_g__setSelectionEnd;
    $a->go_b_c__moveSelectionAfter;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <e/>
      <f/>
      <g/>
    </b>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_b_e__setSelectionStart;
    $a->go_b_f__setSelectionEnd;
    $a->last__moveSelectionFirst;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
    </b>
    <d/>
    <b>
      <e><!-- start --></e>
      <f><!-- end --></f>
      <c/>
    </b>
  </a>
  END

    $a->go_d__setSelectionStart;
    $a->last__setSelectionEnd;
    $a->go_b__moveSelectionLast;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
      <d/>
      <b>
        <e><!-- start --></e>
        <f><!-- end --></f>
        <c/>
      </b>
    </b>
  </a>
  END

mf is a synonym for moveSelectionFirst.

moveSelectionAfter($node, @context)

Move the current selection (if there is one) after the specified $node in the optional @context and return the specified $node on success else undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END
    $a->go_b_1__setSelectionStart;
    $a->go_d__setSelectionEnd;
    $a->first__moveSelectionBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_d_e__setSelectionStart;
    $a->go_d_g__setSelectionEnd;
    $a->go_b_c__moveSelectionAfter;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <e/>
      <f/>
      <g/>
    </b>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_b_e__setSelectionStart;
    $a->go_b_f__setSelectionEnd;
    $a->last__moveSelectionFirst;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
    </b>
    <d/>
    <b>
      <e><!-- start --></e>
      <f><!-- end --></f>
      <c/>
    </b>
  </a>
  END

    $a->go_d__setSelectionStart;
    $a->last__setSelectionEnd;
    $a->go_b__moveSelectionLast;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
      <d/>
      <b>
        <e><!-- start --></e>
        <f><!-- end --></f>
        <c/>
      </b>
    </b>
  </a>
  END

ma is a synonym for moveSelectionAfter.

moveSelectionBefore($node, @context)

Move the current selection (if there is one) before the specified $node in the optional @context and return the specified $node on success else undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END
    $a->go_b_1__setSelectionStart;
    $a->go_d__setSelectionEnd;
    $a->first__moveSelectionBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_d_e__setSelectionStart;
    $a->go_d_g__setSelectionEnd;
    $a->go_b_c__moveSelectionAfter;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <e/>
      <f/>
      <g/>
    </b>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_b_e__setSelectionStart;
    $a->go_b_f__setSelectionEnd;
    $a->last__moveSelectionFirst;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
    </b>
    <d/>
    <b>
      <e><!-- start --></e>
      <f><!-- end --></f>
      <c/>
    </b>
  </a>
  END

    $a->go_d__setSelectionStart;
    $a->last__setSelectionEnd;
    $a->go_b__moveSelectionLast;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
      <d/>
      <b>
        <e><!-- start --></e>
        <f><!-- end --></f>
        <c/>
      </b>
    </b>
  </a>
  END

mb is a synonym for moveSelectionBefore.

moveSelectionLast($node, @context)

Move the current selection (if there is one) so that it is last under the specified $node in the optional @context and return the specified $node on success else undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
  </a>
  END
    $a->go_b_1__setSelectionStart;
    $a->go_d__setSelectionEnd;
    $a->first__moveSelectionBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <e/>
      <f/>
      <g/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_d_e__setSelectionStart;
    $a->go_d_g__setSelectionEnd;
    $a->go_b_c__moveSelectionAfter;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <e/>
      <f/>
      <g/>
    </b>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->go_b_e__setSelectionStart;
    $a->go_b_f__setSelectionEnd;
    $a->last__moveSelectionFirst;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
    </b>
    <d/>
    <b>
      <e><!-- start --></e>
      <f><!-- end --></f>
      <c/>
    </b>
  </a>
  END

    $a->go_d__setSelectionStart;
    $a->last__setSelectionEnd;
    $a->go_b__moveSelectionLast;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <g/>
      <d/>
      <b>
        <e><!-- start --></e>
        <f><!-- end --></f>
        <c/>
      </b>
    </b>
  </a>
  END

ml is a synonym for moveSelectionLast.

Cut and Put

Cut and paste nodes in the parse tree.

cut($node, @context)

Cut out and return the specified $node so that it can be reinserted else where in the parse tree.

     Parameter  Description
  1  $node      Node to cut out
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"/>
    </b>
  </a>
  END


      my $c = $a->go(qw(b c))->cut;                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb"/>
  </a>
  END

x is a synonym for cut.

cutFirst($node, @context)

Cut out the first node below the specified $node if it is in the optional @context and push it on the cut out stack. Return $node on success else return undef. The cut out node can be reinserted using one of the putCutOut(First|Last|Next|Prev) methods.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

putCutOutFirst($node, @context)

Pop the last node placed on the cut out stack by one of the cut(First|Last|Next|Prev) methods and place it first under the specified $node if $node is in the optional @context. Return $node on success else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;


    $a->putCutOutFirst;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

cutLast($node, @context)

Cut out the last node below the specified $node if it is in the optional @context and push it on the cut out stack. Return $node on success else return undef. The cut out node can be reinserted using one of the putCutOut(First|Last|Next|Prev) methods.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

putCutOutLast($node, @context)

Pop the last node placed on the cut out stack by one of the cut(First|Last|Next|Prev) methods and place it last under the specified $node if $node is in the optional @context. Return $node on success else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END


    $a->putCutOutLast;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

cutNext($node, @context)

Cut out the next node beyond the specified $node if it is in the optional @context and push it on the cut out stack. Return the current node on success else return undef. The cut out node can be reinserted using one of the putCutOut(First|Last|Next|Prev) methods.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

putCutOutNext($node, @context)

Pop the last node placed on the cut out stack by one of the cut(First|Last|Next|Prev) methods and place it next after the specified $node if $node is in the optional @context. Return $node on success else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END


    $d->putCutOutNext;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

cutPrev($node, @context)

Cut out the previous node before the specified $node if it is in the optional @context and push it on the cut out stack. Return the current node on success else return undef. The cut out node can be reinserted using one of the putCutOut(First|Last|Next|Prev) methods.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutPrev;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

putCutOutPrev($node, @context)

Pop the last node placed on the cut out stack by one of the cut(First|Last|Next|Prev) methods and place it before the specified $node if $node is in the optional @context. Return $node on success else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    my ($b, $c, $d, $e, $f) = $a->byList;
    $b->cutNext_c_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <e/>
    <f/>
  </a>
  END

    $f->cutPrev_e_a;
    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
    <f/>
  </a>
  END
    $a->cutFirst_b;
    ok -p $a eq <<END;
  <a>
    <d/>
    <f/>
  </a>
  END
    $a->cutLast_f;
    ok -p $a eq <<END;
  <a>
    <d/>
  </a>
  END

    ok @saveLastCutOut == 4;

    $a->putCutOutFirst;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
  </a>
  END

    $a->putCutOutLast;
    ok -p $a eq <<END;
  <a>
    <f/>
    <d/>
    <b/>
  </a>
  END


    $d->putCutOutPrev;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <b/>
  </a>
  END

    $d->putCutOutNext;
    ok -p $a eq <<END;
  <a>
    <f/>
    <e/>
    <d/>
    <c/>
    <b/>
  </a>
  END

cutIfEmpty($node, @context)

Cut out and return the specified $node so that it can be reinserted else where in the parse tree if it is empty.

     Parameter  Description
  1  $node      Node to cut out
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb</b>
    <c/>
    <d></d>
    <e>ee</e>
  </a>
  END

    my (undef, $b, $c, $d, undef, $e) = $a->byList;
    is_deeply [q(b)..q(e)], [map {-t $_} ($b, $c, $d, $e)];


    $c->cutIfEmpty;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>bb</b>
    <d/>
    <e>ee</e>
  </a>
  END


    $d->cutIfEmpty;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>bb</b>
    <e>ee</e>
  </a>
  END


    ok !$_->cutIfEmpty for $a, $b, $e;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

deleteContent($node, @context)

Delete the content of the specified $node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb<c>cc</c>BB
    </b>
  </a>
  END


    $b->deleteContent;                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END

putFirst($old, $new, @context)

Place a cut out or new node at the front of the content of the specified $node and return the new node. See putFirstCut to cut and put first in one operation. See addFirst to perform this operation conditionally.

     Parameter  Description
  1  $old       Original node
  2  $new       New node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"/>
    </b>
  </a>
  END

      my $c = $a->go(qw(b c))->cut;


      $a->putFirst($c);                                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a id="aa">
    <c id="cc"/>
    <b id="bb"/>
  </a>
  END

putFirstCut($first, $second, @context)

Cut out the $second node, place it first under the $first node and return the $second node.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my ($c, $d, $b) = $a->byList;


    $c->putFirstCut($d, qw(c b a));                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

putLast($old, $new, @context)

Place a cut out or new node last in the content of the specified $node and return the new node. See putLastCut to cut and put last in one operation. See addLast to perform this operation conditionally.

     Parameter  Description
  1  $old       Original node
  2  $new       New node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a id="aa">
    <c id="cc"/>
    <b id="bb"/>
  </a>
  END


      $a->putLast($a->go(qw(c))->cut);                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb"/>
    <c id="cc"/>
  </a>
  END

putLastCut($first, $second, @context)

Cut out the $second node, place it last under the $first node and return the $second node.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my ($c, $d, $b) = $a->byList;


    $a->putLastCut($d, qw(a));                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d/>
  </a>
  END

putNext($old, $new, @context)

Place a cut out or new node just after the specified $node and return the new node. See putNextCut to cut and put next in one operation. See addNext to perform this operation conditionally.

     Parameter  Description
  1  $old       Original node
  2  $new       New node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb"/>
    <c id="cc"/>
  </a>
  END


      $a->go(qw(c))->putNext($a->go(q(b))->cut);                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a id="aa">
    <c id="cc"/>
    <b id="bb"/>
  </a>
  END

putNextCut($first, $second, @context)

Cut out the $second node, place it after the $first node and return the $second node.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my ($c, $d, $b) = $a->byList;


    $d->putNextCut($c, qw(d b a));                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <d/>
      <c/>
    </b>
  </a>
  END

putPrev($old, $new, @context)

Place a cut out or new node just before the specified $node and return the new node. See putPrevCut to cut and put previous in one operation. See addPrev to perform this operation conditionally.

     Parameter  Description
  1  $old       Original node
  2  $new       New node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a id="aa">
    <c id="cc"/>
    <b id="bb"/>
  </a>
  END


      $a->go(qw(c))->putPrev($a->go(q(b))->cut);                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb"/>
    <c id="cc"/>
  </a>
  END

putPrevCut($first, $second, @context)

Cut out the $second node, place it before the $first node and return the $second node.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my ($c, $d, $b) = $a->byList;


    $c->putPrevCut($d, qw(c b a));                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <d/>
      <c/>
    </b>
  </a>
  END

Put Siblings or Contents

Move a node and its siblings up and down the parse tree.

putSiblingsFirst($node, @context)

Move the siblings preceding the specified $node in the optional @context down one level and place them first under the specified $node preceding any existing content. Return the specified $node.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/><c/><d/><e/><f/>
  </a>
  END

   my ($b, $c, $d, $e, $f) = $a->byList;


   $d->putSiblingsFirst;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok -p $a eq <<END;
  <a>
    <d>
      <b/>
      <c/>
    </d>
    <e/>
    <f/>
  </a>
  END

putSiblingsLast($node, @context)

Move the siblings following the specified $node in the optional @context down one level so that they are last under the specified $node following any existing content. Return the specified $node.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/><c/><d/><e/><f/>
  </a>
  END

   my ($b, $c, $d, $e, $f) = $a->byList;


   $d->putSiblingsLast;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d>
      <e/>
      <f/>
    </d>
  </a>
  END

putSiblingsAfterParent($node, @context)

Move the specified $node and its following siblings up one level and place them after the parent of the specified $node if the specified $node is in the optional @context. Return the specified $node if the move was made successfully, else confess that the specified move is not possible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>d<e/>
    </b>
  </a>
  END

   my ($c, $d, $e, $b) = $a->byList;


   $d->putSiblingsAfterParent;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
  d
    <e/>
  </a>
  END

putSiblingsBeforeParent($node, @context)

Move the specified $node and its preceding siblings up one level and place them before the parent of the specified $node if the specified $node is in the optional @context. Return the specified $node if the move was made successfully, else confess that the specified move is not possible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>d<e/>
    </b>
  </a>
  END

   my ($c, $d, $e, $b) = $a->byList;


   $d->putSiblingsBeforeParent;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok -p $a eq <<END;
  <a>
    <c/>
  d
    <b>
      <e/>
    </b>
  </a>
  END

putContentAfter($node, @context)

Move the content of the specified $node and place it after that node if that node is in the optional @context. Return the specified $node or confess if the move is not possible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/>
    </b>
  </a>
  END

   my ($c, $d, $b) = $a->byList;


   $b->putContentAfter;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

putContentBefore($node, @context)

Move the content of the specified $node and place it before that node if that node is in the optional @context. Return the specified $node or confess if the move is not possible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/>
    </b>
  </a>
  END

   my ($c, $d, $b) = $a->byList;


   $b->putContentBefore;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   ok -p $a eq <<END;
  <a>
    <c/>
    <d/>
    <b/>
  </a>
  END

Move

Move nodes around in the parse tree by cutting and pasting them.

moveFirst($node, @context)

Move the specified node so that is is the first sibling under its parent. Returns the specified $node on success otherwise undef.

     Parameter  Description
  1  $node      Node to  be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/><c/><d/></a>
  END

    my ($b, $c, $d) = $a->byList;

    $d->moveFirst;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $b->moveLast;

    ok -p $a eq <<END;
  <a>
    <d/>
    <c/>
    <b/>
  </a>
  END

moveLast($node, @context)

Move the specified node so that is is the last sibling under its parent. Returns the specified $node on success otherwise undef.

     Parameter  Description
  1  $node      Node to  be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/><c/><d/></a>
  END

    my ($b, $c, $d) = $a->byList;
    $d->moveFirst;

    $b->moveLast;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <d/>
    <c/>
    <b/>
  </a>
  END

moveStartFirst($node, @context)

Move the start of a $node to contain all of its preceding siblings as children. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b/>
   <c/>
   <d>
    <e/>
   </d>
  </a>
  END

    my ($b, $c, $e, $d) = $a->byList;


    $d->moveStartFirst;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <d>
      <b/>
      <c/>
      <e/>
    </d>
  </a>
  END

moveStartAfter($node, $to, @context)

Move the start end of a $node to just after the specified $target node assuming that the $target node is either a preceding sibling or a child of $node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  $to        Target node
  3  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b/>
   <c/>
   <d>
    <e/>
   </d>
  </a>
  END

    my ($b, $c, $e, $d) = $a->byList;


    $d->moveStartAfter($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
    <d>
      <c/>
      <e/>
    </d>
  </a>
  END


    $d->moveStartAfter($c);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -t $d eq q(d);
    ok -t $c eq q(c);
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d>
      <e/>
    </d>
  </a>
  END


    $d->moveStartAfter($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
    <d/>
  </a>
  END

moveStartBefore($node, $to, @context)

Move the start of a $node to just before the specified $target node assuming that the $target node is either a preceding sibling or a child of $node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $node      Node whose start should be moved
  2  $to        Target node
  3  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b/>
   <c/>
   <d>
    <e/>
   </d>
  </a>
  END

    my ($b, $c, $e, $d) = $a->byList;


    $d->moveStartBefore($c);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
    <d>
      <c/>
      <e/>
    </d>
  </a>
  END


    $d->moveStartBefore($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -t $d eq q(d);
    ok -t $e eq q(e);
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d>
      <e/>
    </d>
  </a>
  END

    $d->moveEndBefore($e);
    ok -t $d eq q(d);
    ok -t $e eq q(e);
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END

moveEndLast($node, @context)

Move the end of a $node to contain all of its following siblings as children. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $node      Node whose end should be moved
  2  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
   </b>
   <d/>
   <e/>
  </a>
  END

    my ($c, $b, $d, $e) = $a->byList;


    $b->moveEndLast;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </a>
  END

moveEndAfter($node, $to, @context)

Move the end of a $node to just after the specified $target node assuming that the $target node is either a subsequent sibling or a child of $node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $node      Node whose end should be moved
  2  $to        Target node
  3  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
   </b>
   <d/>
   <e/>
  </a>
  END

    my ($c,  $b, $d, $e) = $a->byList;


    $b->moveEndAfter($d);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d/>
    </b>
    <e/>
  </a>
  END


    $b->moveEndAfter($c);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d/>
    <e/>
  </a>
  END

moveEndBefore($node, $to, @context)

Move the end of a $node to just before the specified $target node assuming that the $target node is either a subsequent sibling or a child of $node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $node      Node whose end should be moved
  2  $to        Target node
  3  @context   Optional context of node.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>
    <c/>
   </b>
   <d/>
   <e/>
  </a>
  END

    my ($c,  $b, $d, $e) = $a->byList;


    $b->moveEndBefore($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d/>
    </b>
    <e/>
  </a>
  END


    $b->moveEndBefore($d);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d/>
    <e/>
  </a>
  END

putNextFirstCut($node, @context)

Move the specified $node so it is first in the next node with the optional context. Return $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c>
      <d/>
    </c>
  </a>
  END

    my ($b, $d, $c) = $a->byList;

    ok !$b->putNextFirstCut_c_x;

    $b->putNextFirstCut_c_a;
    ok  -p $a eq <<END;
  <a>
    <c>
      <b/>
      <d/>
    </c>
  </a>
  END

putNextFirstCut2($node, @context)

Move the specified $node so it is first in the first node with the specified optional @context of the next node. Return $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c>
      <d/>
    </c>
  </a>
  END

    my ($b, $d, $c) = $a->byList;

    ok !$b->putNextFirstCut2_c_a;

    $b->putNextFirstCut2_d_c_a;

    ok  -p $a eq <<END;
  <a>
    <c>
      <d>
        <b/>
      </d>
    </c>
  </a>
  END

putPrevLastCut($node, @context)

Move the specified $node so it is last in the preceding node with the optional context. Return $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
     <d/>
  </a>
  END

    my ($c, $b, $d) = $a->byList;

    ok !$d->putPrevLastCut_b_c;

    $d->putPrevLastCut_b_a;
    ok  -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

putPrevLastCut2($node, @context)

Move the specified $node so it is last in the last node with the specified optional context of the preceding node. Return the specified $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
     <d/>
  </a>
  END

    my ($c, $b, $d) = $a->byList;

    ok !$d->putPrevLastCut2_c_a;

    $d->putPrevLastCut2_c_b_a;
    ok  -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

putUpNextCut($node, @context)

Move the specified $node, in the optional @context, which must be last under its parent, so that it is next after its parent. Return $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    $a->by(sub{$_->putUpNextCut_d_c_b_a});

    ok -p $a eq <<END
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

putUpNextCut2($node, @context)

Move the specified $node, in the optional @context, if $node is last after its parent which must also be last under its parent, so that $node is next after its grandparent. Return $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    $a->by(sub{$_->putUpNextCut2_d_c_b_a});

    ok -p $a eq <<END
  <a>
    <b>
      <c/>
    </b>
    <d/>
  </a>
  END

putUpPrevCut($node, @context)

Move the specified $node in the optional @context, if $node is first under its parent, so that it is prior to its parent. Return $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    $a->by(sub{$_->putUpPrevCut_d_c_b_a});

    ok -p $a eq <<END
  <a>
    <b>
      <d/>
      <c/>
    </b>
  </a>
  END

putUpPrevCut2($node, @context)

Move the specified $node, in the optional @context, if $node is first under its parent which must also be first under its parent, so that $node is prior to its grandparent. Return the specified $node on success else return undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    $a->by(sub{$_->putUpPrevCut2_d_c_b_a});

    ok -p $a eq <<END
  <a>
    <d/>
    <b>
      <c/>
    </b>
  </a>
  END

moveBlockFirst($start, $end, $parent, @context)

Move the block of siblings starting with $start in the optional context and ending with $end first under the specified $parent node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $end       Last sibling
  3  $parent    Parent to move first under
  4  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
    <d/>
    <e/>
    <f>
      <g/>
    </f>
    <h/>
  </x>
  END
    my ($a, $b, $c, $d, $e, $g, $f, $h) = $x->byList;


    $c->moveBlockFirst($d, $f, qw(c x));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a/>
    <b/>
    <e/>
    <f>
      <c/>
      <d/>
      <g/>
    </f>
    <h/>
  </x>
  END

moveBlockLast($start, $end, $parent, @context)

Move the block of siblings starting with $start in the optional context and ending with $end last under the specified $parent node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $end       Last sibling
  3  $parent    Parent to move last under
  4  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
    <d/>
    <e/>
    <f>
      <g/>
    </f>
    <h/>
  </x>
  END
    my ($a, $b, $c, $d, $e, $g, $f, $h) = $x->byList;


    $c->moveBlockLast($d, $f, qw(c x));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a/>
    <b/>
    <e/>
    <f>
      <g/>
      <c/>
      <d/>
    </f>
    <h/>
  </x>
  END

moveBlockAfter($start, $end, $after, @context)

Move the block of siblings starting with $start in the optional context and ending with $end after the specified $after node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $end       Last sibling
  3  $after     Node to move after
  4  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(q(<x><a/><b/><c/><d/><e/><f/><g/><h/></x>));

    my ($a, $b, $c, $d, $e, $f, $g, $h) = $x->byList;


    $c->moveBlockAfter($d, $f, qw(c x));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -C $x eq q(<a/><b/><e/><f/><c/><d/><g/><h/>);

moveBlockBefore($start, $end, $before, @context)

Move the block of siblings starting with $start in the optional context and ending with $end before the specified $after node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $end       Last sibling
  3  $before    Node to move before
  4  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(q(<x><a/><b/><c/><d/><e/><f/><g/><h/></x>));

    my ($a, $b, $c, $d, $e, $f, $g, $h) = $x->byList;


    $f->moveBlockBefore($g, $b, qw(f x));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -C $x eq q(<a/><f/><g/><b/><c/><d/><e/><h/>);

moveBlockToLastFirst($start, $parent, @context)

Move the siblings starting with $start in the optional context first under the specified $parent node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     Start sibling
  2  $parent    Parent to move first under
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
  </x>
  END
    my ($a, $b, $c) = $x->byList;


    $b->moveBlockToLastFirst($a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a>
      <b/>
      <c/>
    </a>
  </x>
  END

moveBlockToLastLast($start, $parent, @context)

Move the block of siblings starting with $start in the optional context last under the specified $parent node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $parent    Parent to move last under
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>
      <b/>
      <c/>
      <d/>
    </a>
    <e>
      <f/>
      <g/>
      <h/>
    </e>
  </x>
  END
    my ($b, $c, $d, $a, $f, $g, $h, $e) = $x->byList;


    $c->moveBlockToLastLast($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a>
      <b/>
    </a>
    <e>
      <f/>
      <g/>
      <h/>
      <c/>
      <d/>
    </e>
  </x>
  END

moveBlockToLastAfter($start, $after, @context)

Move the block of siblings starting with $start in the optional context after the specified $after node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $after     Node to move after
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>
      <b/>
      <c/>
      <d/>
    </a>
    <e/>
  </x>
  END
    my ($b, $c, $d, $a, $e) = $x->byList;


    $c->moveBlockToLastAfter($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a>
      <b/>
    </a>
    <e/>
    <c/>
    <d/>
  </x>
  END

moveBlockToLastBefore($start, $before, @context)

Move the block of siblings starting with $start in the optional context before the specified $after node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $before    Node to move before
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </x>
  END
    my ($a, $c, $d, $e, $b) = $x->byList;


    $d->moveBlockToLastBefore($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a/>
    <d/>
    <e/>
    <b>
      <c/>
    </b>
  </x>
  END

moveBlockFromFirstFirst($start, $parent, @context)

Move the siblings starting with $start in the optional context first under the specified $parent node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     Start sibling
  2  $parent    Parent to move first under
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>
      <b/>
      <c/>
      <d/>
    </a>
    <e>
      <f/>
      <g/>
      <h/>
    </e>
  </x>
  END
    my ($b, $c, $d, $a, $f, $g, $h, $e) = $x->byList;


    $g->moveBlockFromFirstFirst($a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a>
      <f/>
      <g/>
      <b/>
      <c/>
      <d/>
    </a>
    <e>
      <h/>
    </e>
  </x>
  END

moveBlockFromFirstLast($start, $parent, @context)

Move the block of siblings starting with $start in the optional context last under the specified $parent node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $parent    Parent to move last under
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b/>
    <c/>
  </x>
  END
    my ($a, $b, $c) = $x->byList;


    $b->moveBlockFromFirstLast($c);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <c>
      <a/>
      <b/>
    </c>
  </x>
  END

moveBlockFromFirstAfter($start, $after, @context)

Move the block of siblings starting with $start in the optional context after the specified $after node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $after     Node to move after
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>
      <b/>
      <c/>
      <d/>
    </a>
    <e/>
  </x>
  END
    my ($b, $c, $d, $a, $e) = $x->byList;


    $c->moveBlockFromFirstAfter($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a>
      <d/>
    </a>
    <e/>
    <b/>
    <c/>
  </x>
  END

moveBlockFromFirstBefore($start, $before, @context)

Move the block of siblings starting with $start in the optional context before the specified $after node. Returns $node if the move was made successfully, else confess that the specified move is impossible.

     Parameter  Description
  1  $start     First sibling
  2  $before    Node to move before
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a/>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </x>
  END
    my ($a, $c, $d, $e, $b) = $x->byList;


    $d->moveBlockFromFirstBefore($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <x>
    <a/>
    <c/>
    <d/>
    <b>
      <e/>
    </b>
  </x>
  END

Add selectively

Add new nodes unless they already exist.

addFirst($node, $tag, @context)

Add a new node first below the specified $node with the specified $tag unless a node with that tag already exists in that position. Return the new node if it was created unless return the pre-existing node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag of new node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::newTree(q(a));

    $a->addFirst_b for 1..2;

    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END

addNext($node, $tag, @context)

Add a new node next the specified $node and return the new node unless a node with that tag already exists in which case return the existing $node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag of new node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <b/>
    <e/>
  </a>
  END

    $a->addFirst_b__addNext_c;

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
  </a>
  END

addPrev($node, $tag, @context)

Add a new node before the specified $node with the specified $tag unless a node with that tag already exists in that position. Return the new node if it was created unless return the pre-existing node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag of new node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
  </a>
  END

    $a->addLast_e__addPrev_d;

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END

addLast($node, $tag, @context)

Add a new node last below the specified $node with the specified $tag unless a node with that tag already exists in that position. Return the new node if it was created unless return the pre-existing node..

     Parameter  Description
  1  $node      Node
  2  $tag       Tag of new node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END


    $a->addLast(qw(e)) for 1..2;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
    <e/>
  </a>
  END

addWrapWith($node, $tag, @context)

Wrap the specified $node with the specified tag if the node is not already wrapped with such a tag and return the new node unless a node with that tag already exists in which case return the existing $node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag of new node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(q(<a><b/></a>));

    my $b = $a->first;

    $b->addWrapWith_c for 1..2;

    ok -p $a eq <<END;
  <a>
    <c>
      <b/>
    </c>
  </a>
  END

addSingleChild($node, $tag, @context)

Wrap the content of a specified $node in a new node with the specified $tag unless the content is already wrapped in a single child with the specified $tag.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag of new node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <c>
      <b/>
    </c>
  </a>
  END

    $a->addSingleChild_d for 1..2;

    ok -p $a eq <<END;
  <a>
    <d>
      <c>
        <b/>
      </c>
    </d>
  </a>
  END

Add text selectively

Add new text unless it already exists.

addFirstAsText($node, $text, @context)

Add a new text node first below the specified $node and return the new node unless a text node already exists there and starts with the same text in which case return the existing $node.

     Parameter  Description
  1  $node      Node
  2  $text      Text
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::newTree(q(a));


    $a->addFirstAsText(q(aaaa)) for 1..2;                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $a eq q(<a>aaaa</a>);

addNextAsText($node, $text, @context)

Add a new text node after the specified $node and return the new node unless a text node already exists there and starts with the same text in which case return the existing $node.

     Parameter  Description
  1  $node      Node
  2  $text      Text
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(q(<a><b/></a>));


    $a->go(q(b))->addNextAsText(q(bbbb)) for 1..2;                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
  bbbb
  </a>
  END

addPrevAsText($node, $text, @context)

Add a new text node before the specified $node and return the new node unless a text node already exists there and ends with the same text in which case return the existing $node.

     Parameter  Description
  1  $node      Node
  2  $text      Text
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <b/>
  bbbb
  </a>
  END


    $a->go(q(b))->addPrevAsText(q(aaaa)) for 1..2;                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>aaaa
    <b/>
  bbbb
  </a>
  END

addLastAsText($node, $text, @context)

Add a new text node last below the specified $node and return the new node unless a text node already exists there and ends with the same text in which case return the existing $node.

     Parameter  Description
  1  $node      Node
  2  $text      Text
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -s $a eq q(<a>aaaa</a>);


    $a->addLastAsText(q(dddd)) for 1..2;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -s $a eq q(<a>aaaadddd</a>);

joinWithText($node, $text, $over, @context)

Insert some text between the children of the current $node as specified by $text between all the children of the current $node as long as they all have a tag of $over. Return the current $node on success or undef on failure.

     Parameter  Description
  1  $node      Node
  2  $text      Text
  3  $over      Child tag
  4  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <b/>
    <b/>
  </a>
  END

    $a->joinWithText_CC_b_a;

    ok -p $a eq <<END;
  <a>
    <b/>
  CC
    <b/>
  CC
    <b/>
  </a>
  END

Fission

Split the parent before or after the specified sibling.

splitBefore($node, @context)

Split the parent node into two identical nodes except all the siblings before the specified $node are retained by the existing parent while any following siblings become siblings of the new parent node which is placed after the existing parent. The new parent is returned.

     Parameter  Description
  1  $node      Node to split before
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </a>
  END

    $a->go_b_d__splitBefore;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <d/>
      <e/>
    </b>
  </a>
  END

splitAfter($node, @context)

Split the parent node into two identical nodes except all the siblings after the specified $node are retained by the existing parent while any preceding siblings become siblings of the new parent node which is placed before the existing parent. The new parent is returned

     Parameter  Description
  1  $node      Node to split before
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </a>
  END

    $a->go_b_d__splitAfter;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d/>
    </b>
    <b>
      <e/>
    </b>
  </a>
  END

Fusion

Join consecutive nodes

concatenate($target, $source, @context)

Concatenate two successive nodes and return the $target node.

     Parameter  Description
  1  $target    Target node to replace
  2  $source    Node to concatenate
  3  @context   Optional context of $target

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $s = <<END;
  <a>
    <b>
      <A/>
      <B/>
    </b>
    <c>
      <C/>
      <D/>
    </c>
  </a>
  END

    my $a = Data::Edit::Xml::new($s);


    $a->go(q(b))->concatenate($a->go(q(c)));                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $t = <<END;
  <a>
    <b>
      <A/>
      <B/>
      <C/>
      <D/>
    </b>
  </a>
  END

    ok $t eq -p $a;

concatenateSiblings($node, @context)

Concatenate the nodes that precede and follow the specified $node in the optioonal @context as long as they have the same tag as the specified $node and return the specified $node.

     Parameter  Description
  1  $node      Concatenate around this node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="1"/>
    </b>
    <b>
      <c id="2"/>
    </b>
    <b>
      <c id="3"/>
    </b>
    <b>
      <c id="4"/>
    </b>
  </a>
  END


    $a->go(qw(b 3))->concatenateSiblings;                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c id="1"/>
      <c id="2"/>
      <c id="3"/>
      <c id="4"/>
    </b>
  </a>
  END

mergeDuplicateChildWithParent($parent, @context)

Merge a parent node with its only child if their tags are the same and their attributes do not collide other than possibly the id in which case the parent id is used. Any labels on the child are transferred to the parent. The child node is then unwrapped and the parent node is returned.

     Parameter  Description
  1  $parent    Parent this node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b   id="b" b="bb">
      <b id="c" c="cc"/>
    </b>
  </a>
  END

    my ($c, $b) = $a->byList;

    is_deeply [$b->id, $c->id], [qw(b c)];

    ok $c == $b->hasSingleChild;


    $b->mergeDuplicateChildWithParent;                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b b="bb" c="cc" id="b"/>
  </a>
  END

    ok $b == $a->hasSingleChild;

Put as text

Add text to the parse tree.

putFirstAsText($node, $text, @context)

Add a new text node first under a parent and return the new text node.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be added which might contain unparsed Xml as well as text
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"/>
    </b>
  </a>
  END


    $x->go(qw(b c))->putFirstAsText("<d id=\"dd\">DDDD</d>");                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"><d id="dd">DDDD</d></c>
    </b>
  </a>
  END

putTextFirst($node, @text)

Given a $node place some @text first under the $node and return the new text node else return undef if this is not possible.

     Parameter  Description
  1  $node      The parent node
  2  @text      The text to be added

Example:

    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    my $b = $a->first;

    $b->putTextPrev(qw(Before the B node));
    $b->putTextNext(qw(After the B node));

    $b->putTextFirst(qw(First under the B node));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $b->putTextLast(qw(Last under the B node));

    ok -p $a eq <<END;
  <a>Before the B node
    <b>First under the B node
      <c/>
  Last under the B node
    </b>
  After the B node
  </a>
  END

putLastAsText($node, $text, @context)

Add a new text node last under a parent and return the new text node.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be added which might contain unparsed Xml as well as text
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"><d id="dd">DDDD</d></c>
    </b>
  </a>
  END


    $x->go(qw(b c))->putLastAsText("<e id=\"ee\">EEEE</e>");                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"><d id="dd">DDDD</d><e id="ee">EEEE</e></c>
    </b>
  </a>
  END

putTextLast($node, @text)

Given a $node place some @text last under the $node and return the new text node else return undef if this is not possible.

     Parameter  Description
  1  $node      The parent node
  2  @text      The text to be added

Example:

    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    my $b = $a->first;

    $b->putTextPrev(qw(Before the B node));
    $b->putTextNext(qw(After the B node));
    $b->putTextFirst(qw(First under the B node));

    $b->putTextLast(qw(Last under the B node));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>Before the B node
    <b>First under the B node
      <c/>
  Last under the B node
    </b>
  After the B node
  </a>
  END

putNextAsText($node, $text, @context)

Add a new text node following the specified $node and return the new text node.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be added which might contain unparsed Xml as well as text
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"><d id="dd">DDDD</d><e id="ee">EEEE</e></c>
    </b>
  </a>
  END


    $x->go(qw(b c))->putNextAsText("<n id=\"nn\">NNNN</n>");                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"><d id="dd">DDDD</d><e id="ee">EEEE</e></c>
  <n id="nn">NNNN</n>
    </b>
  </a>
  END

putTextNext($node, @text)

Given a $node place some @text next to the $node and return the new text node else return undef if this is not possible.

     Parameter  Description
  1  $node      The parent node
  2  @text      The text to be added

Example:

    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    my $b = $a->first;

    $b->putTextPrev(qw(Before the B node));

    $b->putTextNext(qw(After the B node));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $b->putTextFirst(qw(First under the B node));
    $b->putTextLast(qw(Last under the B node));

    ok -p $a eq <<END;
  <a>Before the B node
    <b>First under the B node
      <c/>
  Last under the B node
    </b>
  After the B node
  </a>
  END

putPrevAsText($node, $text, @context)

Add a new text node following the specified $node and return the new text node

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be added which might contain unparsed Xml as well as text
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"><d id="dd">DDDD</d><e id="ee">EEEE</e></c>
  <n id="nn">NNNN</n>
    </b>
  </a>
  END


    $x->go(qw(b c))->putPrevAsText("<p id=\"pp\">PPPP</p>");                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a id="aa">
    <b id="bb"><p id="pp">PPPP</p>
      <c id="cc"><d id="dd">DDDD</d><e id="ee">EEEE</e></c>
  <n id="nn">NNNN</n>
    </b>
  </a>
  END

putTextPrev($node, @text)

Given a $node place some @text prior to the $node and return the new text node else return undef if this is not possible.

     Parameter  Description
  1  $node      The parent node
  2  @text      The text to be added

Example:

    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    my $b = $a->first;


    $b->putTextPrev(qw(Before the B node));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $b->putTextNext(qw(After the B node));
    $b->putTextFirst(qw(First under the B node));
    $b->putTextLast(qw(Last under the B node));

    ok -p $a eq <<END;
  <a>Before the B node
    <b>First under the B node
      <c/>
  Last under the B node
    </b>
  After the B node
  </a>
  END

Put as tree

Add parsed text to the parse tree.

putFirstAsTree($node, $text, @context)

Put parsed text first under the specified $node parent and return a reference to the parsed tree. Confess if the text cannot be parsed successfully.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be parsed and added
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a/>));

    ok -p $a eq <<END;
  <a/>
  END


    my $b = $a->putFirstAsTree(q(<b/>));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END

    $b->putNextAsTree(q(<c/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
  </a>
  END

    my $e = $a->putLastAsTree(q(<e/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
  </a>
  END

    $e->putPrevAsTree(q(<d/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END
   }

putLastAsTree($node, $text, @context)

Put parsed text last under the specified $node parent and return a reference to the parsed tree. Confess if the text cannot be parsed successfully.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be parsed and added
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a/>));

    ok -p $a eq <<END;
  <a/>
  END

    my $b = $a->putFirstAsTree(q(<b/>));
    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END

    $b->putNextAsTree(q(<c/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
  </a>
  END


    my $e = $a->putLastAsTree(q(<e/>));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
  </a>
  END

    $e->putPrevAsTree(q(<d/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END
   }

putNextAsTree($node, $text, @context)

Put parsed text after the specified $node parent and return a reference to the parsed tree. Confess if the text cannot be parsed successfully.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be parsed and added
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a/>));

    ok -p $a eq <<END;
  <a/>
  END

    my $b = $a->putFirstAsTree(q(<b/>));
    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END


    $b->putNextAsTree(q(<c/>));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
  </a>
  END

    my $e = $a->putLastAsTree(q(<e/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
  </a>
  END

    $e->putPrevAsTree(q(<d/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END
   }

putPrevAsTree($node, $text, @context)

Put parsed text before the specified $parent parent and return a reference to the parsed tree. Confess if the text cannot be parsed successfully.

     Parameter  Description
  1  $node      The parent node
  2  $text      The string to be parsed and added
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a/>));

    ok -p $a eq <<END;
  <a/>
  END

    my $b = $a->putFirstAsTree(q(<b/>));
    ok -p $a eq <<END;
  <a>
    <b/>
  </a>
  END

    $b->putNextAsTree(q(<c/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
  </a>
  END

    my $e = $a->putLastAsTree(q(<e/>));
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <e/>
  </a>
  END


    $e->putPrevAsTree(q(<d/>));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END
   }

Put as comment

Add some comments to the parse tree relative to the specified $node in the optional $context and return the specified $node.

putFirstAsComment($node, $text, @context)

Put a comment first under the specified $node and return the specified $node.

     Parameter  Description
  1  $node      Parent node
  2  $text      Comment
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END


    $a->putFirstAsComment(q(First));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->putLastAsComment (q(Last));
    $a->go_b_c->putPrevAsComment(q(Before C));
    $a->go_b_c->putNextAsComment(q(After C));

    ok -p $a eq <<END;
  <a><!-- First -->
    <b><!-- Before C -->
      <c/>
  <!-- After C -->
    </b>
  <!-- Last -->
  </a>
  END

putLastAsComment($node, $text, @context)

Put a comment last under the specified $node and return the specified $node.

     Parameter  Description
  1  $node      Parent node
  2  $text      Comment
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->putFirstAsComment(q(First));

    $a->putLastAsComment (q(Last));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->go_b_c->putPrevAsComment(q(Before C));
    $a->go_b_c->putNextAsComment(q(After C));

    ok -p $a eq <<END;
  <a><!-- First -->
    <b><!-- Before C -->
      <c/>
  <!-- After C -->
    </b>
  <!-- Last -->
  </a>
  END

putNextAsComment($node, $text, @context)

Put a comment after the specified $node and return the specified $node

     Parameter  Description
  1  $node      Node
  2  $text      Comment
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->putFirstAsComment(q(First));
    $a->putLastAsComment (q(Last));
    $a->go_b_c->putPrevAsComment(q(Before C));

    $a->go_b_c->putNextAsComment(q(After C));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a><!-- First -->
    <b><!-- Before C -->
      <c/>
  <!-- After C -->
    </b>
  <!-- Last -->
  </a>
  END

putPrevAsComment($node, $text, @context)

Put a comment before the specified $parent parentand return the specified $node

     Parameter  Description
  1  $node      Node
  2  $text      Comment
  3  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->putFirstAsComment(q(First));
    $a->putLastAsComment (q(Last));

    $a->go_b_c->putPrevAsComment(q(Before C));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->go_b_c->putNextAsComment(q(After C));

    ok -p $a eq <<END;
  <a><!-- First -->
    <b><!-- Before C -->
      <c/>
  <!-- After C -->
    </b>
  <!-- Last -->
  </a>
  END

Break in and out

Break nodes out of nodes or push them back

breakIn($start, @context)

Concatenate the nodes following and preceding the start node, unwrapping nodes whose tag matches the start node and return the start node. To concatenate only the preceding nodes, use breakInBackwards, to concatenate only the following nodes, use breakInForwards.

     Parameter  Description
  1  $start     The start node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a>
    <d/>
    <b>
      <c/>
      <c/>
    </b>
    <e/>
    <b>
      <c/>
      <c/>
    </b>
    <d/>
  </a>
  END


      $a->go(qw(b 1))->breakIn;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a>
    <b>
      <d/>
      <c/>
      <c/>
      <e/>
      <c/>
      <c/>
      <d/>
    </b>
  </a>
  END

breakInForwards($start, @context)

Concatenate the nodes following the start node, unwrapping nodes whose tag matches the start node and return the start node in the manner of breakIn.

     Parameter  Description
  1  $start     The start node
  2  @context   Optional context..

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a>
    <d/>
    <b>
      <c/>
      <c/>
    </b>
    <e/>
    <b>
      <c/>
      <c/>
    </b>
    <d/>
  </a>
  END


      $a->go(q(b))->breakInForwards;                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a>
    <d/>
    <b>
      <c/>
      <c/>
      <e/>
      <c/>
      <c/>
      <d/>
    </b>
  </a>
  END

breakInBackwards($start, @context)

Concatenate the nodes preceding the start node, unwrapping nodes whose tag matches the start node and return the start node in the manner of breakIn.

     Parameter  Description
  1  $start     The start node
  2  @context   Optional context..

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $a eq <<END;
  <a>
    <d/>
    <b>
      <c/>
      <c/>
    </b>
    <e/>
    <b>
      <c/>
      <c/>
    </b>
    <d/>
  </a>
  END


      $a->go(qw(b 1))->breakInBackwards;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a>
    <b>
      <d/>
      <c/>
      <c/>
      <e/>
      <c/>
      <c/>
    </b>
    <d/>
  </a>
  END

breakOut($parent, @tags)

Lift child nodes with the specified tags under the specified parent node splitting the parent node into clones and return the cut out original node.

     Parameter  Description
  1  $parent    The parent node
  2  @tags      The tags of the modes to be broken out.

Example:

    my $A = Data::Edit::Xml::new("<a><b><d/><c/><c/><e/><c/><c/><d/></b></a>");


      $a->go(q(b))->breakOut($a, qw(d e));                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $a eq <<END;
  <a>
    <d/>
    <b>
      <c/>
      <c/>
    </b>
    <e/>
    <b>
      <c/>
      <c/>
    </b>
    <d/>
  </a>
  END

breakOutChild($node, @context)

Lift the specified $node up one level splitting its parent. Return the specified $node on success or undef if the operation is not possible.

     Parameter  Description
  1  $node      Node to break out
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </a>
  END

    my ($c, $d, $e, $b) = $a->byList;

    $d->breakOutChild;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d/>
    <b>
      <e/>
    </b>
  </a>
  END

Split and Zip

Move a node up the parse tree by splitting its parent nodes

splitParentAfter($node, @context)

Finish and restart the parent of the specified $node just after the specified $node and return the newly created parent node on success or undef on failure.

     Parameter  Description
  1  $node      The splitting node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </a>
  END

    $a->go_b_d__splitParentAfter;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d/>
    </b>
    <b>
      <e/>
    </b>
  </a>
  END

spa is a synonym for splitParentAfter.

splitParentBefore($node, @context)

Finish and restart the parent of the specified $node just before the specified $node and return the newly created parent node on success or undef on failure.

     Parameter  Description
  1  $node      The splitting node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
      <e/>
    </b>
  </a>
  END

    $a->go_b_d__splitParentBefore;

    ok -p $a ne <<END;
  <a>
    <b>
      <c/>
    </b>
    <b>
      <d/>
      <e/>
    </b>
  </a>
  END

spb is a synonym for splitParentBefore.

splitTo($node, $parent, @context)

Lift the specified $node up until it splits the specified $parent node. Return the specified $node on success or undef if the operation is not possible.

     Parameter  Description
  1  $node      Node to break out
  2  $parent    Ancestral node to split
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

    my ($e, $d, $c, $b) = $a->byList;


    ok !$a->splitTo($a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$b->splitTo($a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $e->splitTo($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

    my ($e, $d, $c, $b) = $a->byList;


    ok !$a->splitTo($a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$b->splitTo($a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok  $e->splitTo($b);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    ok $e->zipDownOnce;                                                           # Invalidates b
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
      <e/>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END


   ok  $e->splitTo($a->first);                                                    # b invalidated by zipDownOnce  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   $e->zipDown;

   ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

adoptChild($parent, $child, @context)

Lift the specified $child node up until it is an immediate child of the specified $parent node by splitting any intervening nodes. Return the specified $child node on success or undef if the operation is not possible.

     Parameter  Description
  1  $parent    Adopting parent node
  2  $child     Child node to adopt
  3  @context   Optional context of child

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

    my ($e, $d, $c, $b) = $a->byList;


    $a->adoptChild($e);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    $e->zipDown;
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

zipDownOnce($node, @context)

Push a node down one level by making it a child of a node formed by merging the preceding and following siblings if they have the same tag.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

    my ($e, $d, $c, $b) = $a->byList;

    ok !$a->splitTo($a);
    ok !$b->splitTo($a);
    ok  $e->splitTo($b);

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END


    ok $e->zipDownOnce;                                                           # Invalidates b  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
      <e/>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END


   ok  $e->splitTo($a->first);                                                    # b invalidated by zipDownOnce  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   $e->zipDown;

   ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

zipDown($node, @context)

Push a node down as many levels as possible by making it a child of a node formed by merging the preceding and following siblings if they have the same tag.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

    my ($e, $d, $c, $b) = $a->byList;

    $a->adoptChild($e);
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END


    $e->zipDown;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END


    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

    my ($e, $d, $c, $b) = $a->byList;

    ok !$a->splitTo($a);
    ok !$b->splitTo($a);
    ok  $e->splitTo($b);

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    ok $e->zipDownOnce;                                                           # Invalidates b
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
      <e/>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

   ok  $e->splitTo($a->first);                                                    # b invalidated by zipDownOnce

   $e->zipDown;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d>
          <e/>
        </d>
      </c>
    </b>
  </a>
  END

splitAndWrapFromStart($parent, $split, $wrap, %attributes)

Split the child nodes of $parent on the child nodes with a tag of $split wrapping the splitting node and all preceding nodes from the previous splitting node or the start with the specified $wrapping node with optional %attributes. Returns an array of the wrapping nodes created.

     Parameter    Description
  1  $parent      Parent node
  2  $split       Tag of splitting nodes
  3  $wrap        Tag for wrapping node
  4  %attributes  Attributes for wrapping nodes

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <PP/>
    <b>
      <c/>
    </b>
    <QQ/>
    <b>
      <d/>
    </b>
    <RR/>
    <b>
      <e/>
    </b>
    <SS/>
  </a>
  END

    my $a = $A->clone;

    ok 3 == $a->splitAndWrapFromStart(qw(b B));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <B>
      <PP/>
      <b>
        <c/>
      </b>
    </B>
    <B>
      <QQ/>
      <b>
        <d/>
      </b>
    </B>
    <B>
      <RR/>
      <b>
        <e/>
      </b>
    </B>
    <SS/>
  </a>
  END


    my $b = $A->clone;
    ok 3 == $b->splitAndWrapToEnd(qw(b B));

    ok -p $b eq <<END;
  <a>
    <PP/>
    <B>
      <b>
        <c/>
      </b>
      <QQ/>
    </B>
    <B>
      <b>
        <d/>
      </b>
      <RR/>
    </B>
    <B>
      <b>
        <e/>
      </b>
      <SS/>
    </B>
  </a>
  END

splitAndWrapToEnd($parent, $split, $wrap, %attributes)

Split the sequence of child nodes under the specified $parent node on those child nodes whose tag value is $split wrapping the splitting node and all following nodes up until the next splitting node or the end of the sequence with newly created nodes whose tag is $wrap with optional attributes %attributes. Returns an array of the wrapping nodes so created.

     Parameter    Description
  1  $parent      Parent node
  2  $split       Tag of splitting nodes
  3  $wrap        Tag for wrapping node
  4  %attributes  Attributes for wrapping nodes

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <PP/>
    <b>
      <c/>
    </b>
    <QQ/>
    <b>
      <d/>
    </b>
    <RR/>
    <b>
      <e/>
    </b>
    <SS/>
  </a>
  END

    my $a = $A->clone;
    ok 3 == $a->splitAndWrapFromStart(qw(b B));

    ok -p $a eq <<END;
  <a>
    <B>
      <PP/>
      <b>
        <c/>
      </b>
    </B>
    <B>
      <QQ/>
      <b>
        <d/>
      </b>
    </B>
    <B>
      <RR/>
      <b>
        <e/>
      </b>
    </B>
    <SS/>
  </a>
  END


    my $b = $A->clone;

    ok 3 == $b->splitAndWrapToEnd(qw(b B));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $b eq <<END;
  <a>
    <PP/>
    <B>
      <b>
        <c/>
      </b>
      <QQ/>
    </B>
    <B>
      <b>
        <d/>
      </b>
      <RR/>
    </B>
    <B>
      <b>
        <e/>
      </b>
      <SS/>
    </B>
  </a>
  END

Replace

Replace nodes in the parse tree with nodes or text

replaceWith($old, $new, @context)

Replace a node (and all its content) with a new node (and all its content) and return the new node. If the node to be replaced is the root of the parse tree then no action is taken other then returning the new node.

     Parameter  Description
  1  $old       Old node
  2  $new       New node
  3  @context   Optional context..

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

     {my $x = Data::Edit::Xml::new(qq(<a><b><c id="cc"/></b></a>));


      $x->go(qw(b c))->replaceWith($x->newTag(qw(d id dd)));                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -s $x eq '<a><b><d id="dd"/></b></a>';

replaceWithText($old, $text, @context)

Replace a node (and all its content) with a new text node and return the new node.

     Parameter  Description
  1  $old       Old node
  2  $text      Text of new node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

     {my $x = Data::Edit::Xml::new(qq(<a><b><c id="cc"/></b></a>));


      $x->go(qw(b c))->replaceWithText(qq(BBBB));                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -s $x eq '<a><b>BBBB</b></a>';

replaceWithBlank($old, @context)

Replace a node (and all its content) with a new blank text node and return the new node.

     Parameter  Description
  1  $old       Old node
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

     {my $x = Data::Edit::Xml::new(qq(<a><b><c id="cc"/></b></a>));


      $x->go(qw(b c))->replaceWithBlank;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -s $x eq '<a><b> </b></a>';

replaceContentWithMovedContent($node, @nodes)

Replace the content of a specified target node with the contents of the specified source nodes removing the content from each source node and return the target node.

     Parameter  Description
  1  $node      Target node
  2  @nodes     Source nodes

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
       <b1/>
       <b2/>
    </b>
    <c>
       <c1/>
       <c2/>
    </c>
    <d>
       <d1/>
       <d2/>
    </d>
  </a>
  END

    my ($b, $c, $d) = $a->contents;


    $d->replaceContentWithMovedContent($c, $b);                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d>
      <c1/>
      <c2/>
      <b1/>
      <b2/>
    </d>
  </a>
  END

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <d>
       <b>
         <b1/>
         <b2/>
      </b>
      <c>
         <c1/>
         <c2/>
      </c>
    </d>
  </a>
  END

    my ($d)     = $a->contents;

    my ($b, $c) = $d->contents;


    $d->replaceContentWithMovedContent($c, $b);                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <d>
      <c1/>
      <c2/>
      <b1/>
      <b2/>
    </d>
  </a>
  END

replaceContentWith($node, @content)

Replace the content of a node with the specified nodes and return the replaced content

     Parameter  Description
  1  $node      Node whose content is to be replaced
  2  @content   New content

Example:

     {my $x = Data::Edit::Xml::new(qq(<a><b/><c/></a>));


      $x->replaceContentWith(map {$x->newTag($_)} qw(B C));                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -s $x eq '<a><B/><C/></a>';

replaceContentWithText($node, @text)

Replace the content of a node with the specified texts and return the replaced content

     Parameter  Description
  1  $node      Node whose content is to be replaced
  2  @text      Texts to form new content

Example:

     {my $x = Data::Edit::Xml::new(qq(<a><b/><c/></a>));


      $x->replaceContentWithText(qw(b c));                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -s $x eq '<a>bc</a>';

Swap

Swap nodes both singly and in blocks

invert($parent, @context)

Swap a parent and child node where the child is the only child of the parent and return the parent.

     Parameter  Description
  1  $parent    Parent
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b">
      <c id="c">
        <d/>
        <e/>
      </c>
    </b>
  </a>
  END


    $a->first->invert;                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <c id="c">
      <b id="b">
        <d/>
        <e/>
      </b>
    </c>
  </a>
  END


    $a->first->invert;                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b id="b">
      <c id="c">
        <d/>
        <e/>
      </c>
    </b>
  </a>
  END

invertFirst($parent, @context)

Swap a parent and child node where the child is the first child of the parent by placing the parent last in the child. Return the parent.

     Parameter  Description
  1  $parent    Parent
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
        <e/>
      </c>
      <f/>
      <g/>
    </b>
  </a>
  END

    ok -p $a eq <<END;
  <a>
    <c>
      <d/>
      <e/>
      <b>
        <f/>
        <g/>
      </b>
    </c>
  </a>
  END

invertLast($parent, @context)

Swap a parent and child node where the child is the last child of the parent by placing the parent first in the child. Return the parent.

     Parameter  Description
  1  $parent    Parent
  2  @context   Context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
        <e/>
      </c>
      <f/>
      <g/>
    </b>
  </a>
  END

    ok -p $a eq <<END;
  <a>
    <c>
      <d/>
      <e/>
      <b>
        <f/>
        <g/>
      </b>
    </c>
  </a>
  END

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
        <e/>
      </c>
      <f/>
      <g/>
    </b>
  </a>
  END

swap($first, $second, @context)

Swap two nodes optionally checking that the first node is in the specified context and return the first node.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok <<END eq -p $x;
  <x>
    <a a="1" b="2"/>
    <b/>
    <c a="1" b="3" c="4"/>
  </x>
  END


    $a->swap($c);                                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $x;
  <x>
    <c a="1" b="3" c="4"/>
    <b/>
    <a a="1" b="2"/>
  </x>
  END

swapFirstSibling($node, @context)

Swap $node with its first sibling node and return $node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
    <g/>
  </a>
  END

    $a->go_f__swapFirstSibling;

    ok -p $a eq <<END;
  <a>
    <f/>
    <c/>
    <d/>
    <e/>
    <b/>
    <g/>
  </a>
  END

    $a->go_c__swapLastSibling;

    ok -p $a eq <<END;
  <a>
    <f/>
    <g/>
    <d/>
    <e/>
    <b/>
    <c/>
  </a>
  END

sfs is a synonym for swapFirstSibling.

swapNext($node, @context)

Swap $node with its following node if $$node matches the first element of the specified context and the next node matches the rest. Return the node that originally followed $node on success or undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
        <e/>
      </c>
      <f>
        <g/>
      </f>
    </b>
  </a>
  END

    my ($d, $e, $c, $g, $f, $b) = $a->byList;

    ok -t $b eq q(b);


    $d->swapNext; $g->swapPrev;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $d->after($e);
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <e/>
        <d/>
      </c>
      <f>
        <g/>
      </f>
    </b>
  </a>
  END


    $d->swapPrev; $c->swapNext;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $f->before($c);
    ok -p $a eq <<END;
  <a>
    <b>
      <f>
        <g/>
      </f>
      <c>
        <d/>
        <e/>
      </c>
    </b>
  </a>
  END

sn is a synonym for swapNext.

swapPrev($node, @context)

Swap $node with its preceding node if $$node matches the first element of the specified context and the previous node matches the rest. Return the node that originally followed $node on success or undef on failure.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
        <e/>
      </c>
      <f>
        <g/>
      </f>
    </b>
  </a>
  END

    my ($d, $e, $c, $g, $f, $b) = $a->byList;

    ok -t $b eq q(b);


    $d->swapNext; $g->swapPrev;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $d->after($e);
    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <e/>
        <d/>
      </c>
      <f>
        <g/>
      </f>
    </b>
  </a>
  END


    $d->swapPrev; $c->swapNext;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $f->before($c);
    ok -p $a eq <<END;
  <a>
    <b>
      <f>
        <g/>
      </f>
      <c>
        <d/>
        <e/>
      </c>
    </b>
  </a>
  END

sp is a synonym for swapPrev.

swapLastSibling($node, @context)

Swap $node with its last sibling node and return $node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
    <f/>
    <g/>
  </a>
  END

    $a->go_f__swapFirstSibling;

    ok -p $a eq <<END;
  <a>
    <f/>
    <c/>
    <d/>
    <e/>
    <b/>
    <g/>
  </a>
  END

    $a->go_c__swapLastSibling;

    ok -p $a eq <<END;
  <a>
    <f/>
    <g/>
    <d/>
    <e/>
    <b/>
    <c/>
  </a>
  END

sls is a synonym for swapLastSibling.

swapTags($first, $second, @context)

Swap the tags of two nodes optionally checking that the first node is in the specified context and return ($first, $second) nodes.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END


    $a->swapTags($a->first);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <b>
    <a>
      <c/>
    </a>
  </b>
  END

    my ($C, $A) = $a->downWhileFirst->swapTagWithParent;
    ok -t $A eq q(a);
    ok -t $C eq q(c);
    ok -p $a eq <<END;
  <b>
    <c>
      <a/>
    </c>
  </b>
  END

swapTagWithParent($node, @context)

Swap the tags of the specified $node and its parent optionally checking that the $node is in the specified context and return (parent of $node, $node) or () if there is no such parent node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->swapTags($a->first);
    ok -p $a eq <<END;
  <b>
    <a>
      <c/>
    </a>
  </b>
  END


    my ($C, $A) = $a->downWhileFirst->swapTagWithParent;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -t $A eq q(a);
    ok -t $C eq q(c);
    ok -p $a eq <<END;
  <b>
    <c>
      <a/>
    </c>
  </b>
  END

reorder($node, $first, $second, @context)

If the current $node has a context of ($first, @context) and the preceding node has a context of ($second, @context), then swap the current node with the previous node.Return the current node regardless

     Parameter  Description
  1  $node      Node
  2  $first     First tag
  3  $second    Second tag
  4  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <d>
      <c/>
    </d>
    <b>
      <c/>
    </b>
  </a>
  END

    $a->by(sub {$_->reorder_b_d_a});

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <c/>
    </d>
  </a>
  END

    $a->by(sub {$_->reorder_b_d_a});

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d>
      <c/>
    </d>
  </a>
  END

Wrap and unwrap

Wrap and unwrap nodes to alter the depth of the parse tree

Wrap

Wrap nodes to deepen the parse tree

wrapWith($node, $tag, @context)

Wrap the specified $node in a new node created from the specified $tag in the optional @context forcing the specified $node down to deepen the parse tree - return the new wrapping node or undef if this is not possible. See addWrapWith to perform this operation conditionally.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag for the new node or tag
  3  @context   Optional context

Example:

    ok -p $x eq <<END;
  <a>
    <b>
      <c id="11"/>
    </b>
  </a>
  END


    $x->go(qw(b c))->wrapWith(qw(C));                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a>
    <b>
      <C>
        <c id="11"/>
      </C>
    </b>
  </a>
  END

wrapWithDup($node, @context)

Wrap the specified $node in a new node with the same tag as $node in the optional @context making $node an only child of the new node. Return the new wrapping node or undef if this is not possible.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/></b></a>
  END

    my ($c, $b) = $a->byList;


    $c->wrapWithDup->id = 'c';  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="c">
        <c/>
      </c>
    </b>
  </a>
  END

    $b->wrapContentWithDup->id = 'b';
    ok -p $a eq <<END;
  <a>
    <b>
      <b id="b">
        <c id="c">
          <c/>
        </c>
      </b>
    </b>
  </a>
  END

wrapUp($node, @tags)

Wrap the specified $node in a sequence of new nodes created from the specified @tags forcing the original node down - deepening the parse tree - return the array of wrapping nodes if want array else the last wrapping node.

     Parameter  Description
  1  $node      Node to wrap
  2  @tags      Tags to wrap the node with - with the uppermost tag rightmost.

Example:

    my $c = Data::Edit::Xml::newTree("c", id=>33);


    my ($b, $a) = $c->wrapUp(qw(b a));                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<'END';
  <a>
    <b>
      <c id="33"/>
    </b>
  </a>
  END

wrapWithN($node, $N, @context)

Wrap this $node with the first $N elements of @context. If @context contains more then $N entries, the remainder are checked as the context of $node. Returns the upper most wrapping node or undef if the specified $node does not match these conditions.

     Parameter  Description
  1  $node      Node
  2  $N         Number of tags wrapping tags
  3  @context   Tags and optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <d/>
  </a>
  END

    ok !$a->go_d__wrapWithN_2_c_b_a;
    $a->by(sub{$_->wrapWithN_2_c_b_d_a});

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

wrapWithAll($node, @tags)

Wrap this $node wrapped with the specified @tags and return the last wrapping node.

     Parameter  Description
  1  $node      Node
  2  @tags      Tags

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <d/>
  </a>
  END

    $a->go_d__wrapWithAll_c_b;

    ok -p $a eq <<END;
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

    my $a = Data::Edit::Xml::new(q(<a id="c4"/>));
    my $b = Data::Edit::Xml::new(q(<a id="c5"/>));

    ok -M $a eq -M $b;

ww is a synonym for wrapWithAll.

wrapDown($node, @tags)

Wrap the content of the specified $node in a sequence of new nodes forcing the original node up - deepening the parse tree - return the array of wrapping nodes if want array else the last wrapping node.

     Parameter  Description
  1  $node      Node to wrap
  2  @tags      Tags to wrap the node with - with the uppermost tag rightmost.

Example:

    my $a = Data::Edit::Xml::newTree("a", id=>33);


    my ($b, $c) = $a->wrapDown(qw(b c));                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a id="33">
    <b>
      <c/>
    </b>
  </a>
  END

wrapContentWith($old, $tag, %attributes)

Wrap the content of the specified $node in a new node created from the specified $tag and %attributes: the specified $node then contains just the new node which, in turn, contains all the content of the specified $node.

Returns the new wrapping node.

     Parameter    Description
  1  $old         Node
  2  $tag         Tag for new node
  3  %attributes  Attributes for new node.

Example:

    ok -p $x eq <<END;
  <a>
    <b>
      <c/>
      <c/>
      <c/>
    </b>
  </a>
  END


    $x->go(q(b))->wrapContentWith(qw(D id DD));                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <a>
    <b>
      <D id="DD">
        <c/>
        <c/>
        <c/>
      </D>
    </b>
  </a>
  END

    ok -p $a eq <<END;
  <a>
    <b id="1"/>
    <c id="2"/>
    <d id="3"/>
    <c id="4"/>
    <d id="5"/>
    <e id="6"/>
    <b id="7"/>
    <c id="8"/>
    <d id="9"/>
    <f id="10"/>
  </a>
  END

wcw is a synonym for wrapContentWith.

wrapContentWithDup($node, @context)

Wrap the content if the specified $node in a new node with the same tag as $node in the optional @context making the new node an only child of $node. Return the new wrapping node or undef if this is not possible.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/></b></a>
  END

    my ($c, $b) = $a->byList;

    $c->wrapWithDup->id = 'c';
    ok -p $a eq <<END;
  <a>
    <b>
      <c id="c">
        <c/>
      </c>
    </b>
  </a>
  END


    $b->wrapContentWithDup->id = 'b';  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <a>
    <b>
      <b id="b">
        <c id="c">
          <c/>
        </c>
      </b>
    </b>
  </a>
  END

wrapSiblingsBefore($node, $tag, %attributes)

If there are any siblings before the specified $node, wrap them with a new node created from the specified $tag and %attributes and return the newly created node.

Returns undef if the specified $node is the first node under its parent.

     Parameter    Description
  1  $node        Node to wrap before
  2  $tag         Tag for new node
  3  %attributes  Attributes for new node.

Example:

   {my $a = Data::Edit::Xml::new(q(<a><b/><c/><d/></a>));

    my ($b, $c, $d) = $a->byList;


    $c->wrapSiblingsBefore(q(X));                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <X>
      <b/>
    </X>
    <c/>
    <d/>
  </a>
  END

wrapFromFirst($node, $tag, %attributes)

Wrap this $node and any preceding siblings with a new node created from the specified $tag and %attributes and return the wrapping node.

     Parameter    Description
  1  $node        Node to wrap before
  2  $tag         Tag for new node
  3  %attributes  Attributes for new node.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b/><c/><d/></a>));

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    $a->go_c->wrapFromFirst_B;
    ok -p $a eq <<END;
  <a>
    <B>
      <b/>
      <c/>
    </B>
    <d/>
  </a>
  END
   }

wrapFromFirstOrLastIn($node, $tag, @targets)

Wrap inclusively from the first sibling node to the specified $node or from the last prior sibling node whose tag matches one of the tags in @targets to the specified $node using $tag as the tag of the wrapping node and return the wrapping node.

     Parameter  Description
  1  $node      Node at which to start to wrap
  2  $tag       Wrapping tag
  3  @targets   Tags at which to end the wrap.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/><c/><d/><e/><f/></a>
  END

    $a->go_d__wrapFromFirstOrLastIn_g_a_b_c;
    ok -p $a eq <<END;
  <a>
    <b/>
    <g>
      <c/>
      <d/>
    </g>
    <e/>
    <f/>
  </a>
  END

    $a->go_e__wrapFromFirstOrLastIn_i_A_B_C;
    ok -p $a eq <<END;
  <a>
    <i>
      <b/>
      <g>
        <c/>
        <d/>
      </g>
      <e/>
    </i>
    <f/>
  </a>
  END

wrapFirstN($node, $N, $tag, @context)

Wrap the first $N nodes under this $node in the optional @context with the specified $tag and return the new node or undef if there are no such nodes to wrap.

     Parameter  Description
  1  $node      Node
  2  $N         Number of nodes to wrap
  3  $tag       Wrapping tag
  4  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    $a->wrapFirstN_2_Z;

    ok -p $a eq <<END;
  <a>
    <Z>
      <b/>
      <c/>
    </Z>
    <d/>
  </a>
  END

wrapSiblingsBetween($first, $last, $tag, %attributes)

If there are any siblings between the specified $nodes, wrap them with a new node created from the specified $tag and %attributes. Return the wrapping node else undef if there are no nodes to wrap.

     Parameter    Description
  1  $first       First sibling
  2  $last        Last sibling
  3  $tag         Tag for new node
  4  %attributes  Attributes for new node.

Example:

   {my $a = Data::Edit::Xml::new(q(<a><b/><c/><d/></a>));

    my ($b, $c, $d) = $a->byList;


    $b->wrapSiblingsBetween($d, q(Y));                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
    <Y>
      <c/>
    </Y>
    <d/>
  </a>
  END

wrapSiblingsAfter($node, $tag, %attributes)

If there are any siblings after the specified $node, wrap them with a new node created from the specified $tag and %attributes and return the newly created node.

Returns undef if the specified $node is the last node under its parent.

     Parameter    Description
  1  $node        Node to wrap before
  2  $tag         Tag for new node
  3  %attributes  Attributes for new node.

Example:

   {my $a = Data::Edit::Xml::new(q(<a><b/><c/><d/></a>));

    my ($b, $c, $d) = $a->byList;


    $c->wrapSiblingsAfter(q(Y));                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <Y>
      <d/>
    </Y>
  </a>
  END

wrapNext($node, $tag, @context)

Wrap this $node and the following sibling with a new node created from the specified $tag. If the optional context is specified then it should match the first node, next node and the context of the parent of the $node as far as it is specified. Return the new node created or undef on failure.

     Parameter  Description
  1  $node      Node to wrap before
  2  $tag       Tag for new node
  3  @context   Context.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    my ($b, $c, $d) = $a->byList;

    $b->wrapNext_e;
    ok  -p $a eq <<END;
  <a>
    <e>
      <b/>
      <c/>
    </e>
    <d/>
  </a>
  END

wrapNextN($node, $N, $tag, @context)

Wrap this $nodeand the next $N-1 nodes following this $node in the optional @context with the specified $tag and return the new node or undef if there are no such nodes to wrap.

     Parameter  Description
  1  $node      Node
  2  $N         Number of nodes to wrap
  3  $tag       Wrapping tag
  4  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END

    $a->go_c__wrapNextN_2_Z;

    ok -p $a eq <<END;
  <a>
    <b/>
    <Z>
      <c/>
      <d/>
    </Z>
    <e/>
  </a>
  END

wrapPrev($node, $tag, @context)

Wrap this $node and the preceding sibling with a new node created from the specified $tag. If the optional context is specified then it should match the first node, previous node and the context of the parent of the $node as far as it is specified. Return the new node created or undef on failure.

     Parameter  Description
  1  $node      Node to wrap before
  2  $tag       Tag for new node
  3  @context   Context.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    my ($b, $c, $d) = $a->byList;

    $c->wrapPrev_e;
    ok  -p $a eq <<END;
  <a>
    <e>
      <b/>
      <c/>
    </e>
    <d/>
  </a>
  END

wrapPrevN($node, $N, $tag, @context)

Wrap this $nodeand the previous $N-1 nodes following this $node in the optional @context with the specified $tag and return the new node or undef if there are no such nodes to wrap.

     Parameter  Description
  1  $node      Node
  2  $N         Number of nodes to wrap
  3  $tag       Wrapping tag
  4  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
    <e/>
  </a>
  END

    $a->go_d__wrapPrevN_2_Z;

    ok -p $a eq <<END;
  <a>
    <b/>
    <Z>
      <c/>
      <d/>
    </Z>
    <e/>
  </a>
  END

wrapToLast($node, $tag, %attributes)

Wrap this $node and any following siblings with a new node created from the specified $tag and %attributes and return the wrapping node.

     Parameter    Description
  1  $node        Node to wrap before
  2  $tag         Tag for new node
  3  %attributes  Attributes for new node.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a><b/><c/><d/></a>));

    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    $a->go_c->wrapToLast_D;
    ok -p $a eq <<END;
  <a>
    <b/>
    <D>
      <c/>
      <d/>
    </D>
  </a>
  END
   }

wrapToLastOrFirstIn($node, $tag, @targets)

Wrap this $node and any following siblings, up to and including the first sibling that matches one of the specified @find nodes or all following siblings if no such match occurs, with a new node created from the specified $tag and return the new wrapping node.

     Parameter  Description
  1  $node      Node at which to start to wrap
  2  $tag       Wrapping tag
  3  @targets   Tags at which to end the wrap.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b/><c/><d/><e/><f/></a>
  END

    $a->go_e__wrapToLastOrFirstIn_g_h;
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <d/>
    <g>
      <e/>
      <f/>
    </g>
  </a>
  END

    $a->go_d__wrapToLastOrFirstIn_h_g_c;
    ok -p $a eq <<END;
  <a>
    <b/>
    <c/>
    <h>
      <d/>
      <g>
        <e/>
        <f/>
      </g>
    </h>
  </a>
  END

    $a->go_c__wrapToLastOrFirstIn_i_c;
    ok -p $a eq <<END;
  <a>
    <b/>
    <i>
      <c/>
      <h>
        <d/>
        <g>
          <e/>
          <f/>
        </g>
      </h>
    </i>
  </a>
  END

wrapLastN($node, $N, $tag, @context)

Wrap the last $N nodes under this $node in the optional @context with the specified $tag and return the new node or undef if there are no such nodes to wrap.

     Parameter  Description
  1  $node      Node
  2  $N         Number of nodes to wrap
  3  $tag       Wrapping tag
  4  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
    <c/>
    <d/>
  </a>
  END

    $a->wrapLastN_2_Z;

    ok -p $a eq <<END;
  <a>
    <b/>
    <Z>
      <c/>
      <d/>
    </Z>
  </a>
  END

wrapTo($start, $end, $tag, %attributes)

Wrap all the nodes from the $start node to the $end node inclusive with a new node created from the specified $tag and %attributes and return the new node.

Return undef if the $start and $end nodes are not siblings - they must have the same parent for this method to work.

     Parameter    Description
  1  $start       Start node
  2  $end         End node
  3  $tag         Tag for the wrapping node
  4  %attributes  Attributes for the wrapping node

Example:

    my $x = Data::Edit::Xml::new(my $s = <<END);
  <aa>
    <a>
      <b/>
        <c id="1"/><c id="2"/><c id="3"/><c id="4"/>
      <d/>
    </a>
  </aa>
  END


    $x->go(qw(a c))->wrapTo($x->go(qw(a c -1)), qq(C), id=>1234);                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <aa>
    <a>
      <b/>
      <C id="1234">
        <c id="1"/>
        <c id="2"/>
        <c id="3"/>
        <c id="4"/>
      </C>
      <d/>
    </a>
  </aa>
  END

    my $C = $x->go(qw(a C));


    $C->wrapTo($C, qq(D));                                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $x eq <<END;
  <aa>
    <a>
      <b/>
      <D>
        <C id="1234">
          <c id="1"/>
          <c id="2"/>
          <c id="3"/>
          <c id="4"/>
        </C>
      </D>
      <d/>
    </a>
  </aa>
  END

    ok -p $a eq <<END;
  <a>
    <b>
      <D id="DD">
        <c id="0"/>
        <c id="1"/>
      </D>
      <E id="EE">
        <c id="2"/>
      </E>
      <F id="FF">
        <c id="3"/>
      </F>
    </b>
  </a>
  END

wrapFrom($end, $start, $tag, %attributes)

Wrap all the nodes from the $start node to the $end node with a new node created from the specified $tag and %attributes and return the new node. Return undef if the $start and $end nodes are not siblings - they must have the same parent for this method to work.

     Parameter    Description
  1  $end         End node
  2  $start       Start node
  3  $tag         Tag for the wrapping node
  4  %attributes  Attributes for the wrapping node

Example:

   {my $a = Data::Edit::Xml::new(my $s = <<END);
  <a>
    <b>
      <c id="0"/><c id="1"/><c id="2"/><c id="3"/>
    </b>
  </a>
  END

    my $b = $a->first;

    my @c = $b->contents;


    $c[1]->wrapFrom($c[0], qw(D id DD));                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <D id="DD">
        <c id="0"/>
        <c id="1"/>
      </D>
      <c id="2"/>
      <c id="3"/>
    </b>
  </a>
  END

Unwrap

Unwrap nodes to reduce the depth of the parse tree

unwrap($node, @context)

Unwrap the specified $node if in the optional @context by replacing the node with its contents. Returns the parent node on success, otherwise undef if an attempt is made to unwrap a text node or the root node.

     Parameter  Description
  1  $node      Node to unwrap
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $x = Data::Edit::Xml::new(q(<a>A<b/>B</a>));
    my $b = $x->go_b;
    $b->putFirst($x->newText(' c '));
    ok -s $x eq q(<a>A<b> c </b>B</a>);

    $b->unwrap;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -s $x eq q(<a>A c B</a>);
   }

u is a synonym for unwrap.

unwrapParentOfOnlyChild($node, @context)

Unwrap the parent of the specified $node in the optional @context when the $node is the only child of its parent. Return the specified $node regardless unless the node is not in the optional context in which case return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END


    $a->go_b_c->unwrapParentOfOnlyChild;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <c/>
  </a>
  END

unwrapOnlyChild($node, @context)

Unwrap the specified $node in the optional @context when the $node is the only child of its parent. Return the specified $node regardless unless the node is not in the optional context in which case return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
    <d/>
  </a>
  END


    $a->go_b->unwrapOnlyChild;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
    </b>
    <d/>
  </a>
  END


    $a->go_b_c->unwrapOnlyChild;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b/>
    <d/>
  </a>
  END

unwrapParentsWithSingleChild($node, @context)

Unwrap any immediate ancestors of the specified $node in the optional @context which have only a single child and return the specified $node regardless unless the node is not in the optional context in which case return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <e/>
  </a>
  END


    $a->go(qw(b c d))->unwrapParentsWithSingleChild;                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <d/>
    <e/>
  </a>
  END

unwrapContentsKeepingText($node, @context)

Unwrap all the non text nodes below the specified $node adding a leading and a trailing space to prevent unwrapped content from being elided and return the specified $node else undef if not in the optional @context.

     Parameter  Description
  1  $node      Node to unwrap
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

      ok -p $x eq <<END;
  <a>
    <b>
      <c>
        <d>DD</d>
  EE
        <f>FF</f>
      </c>
    </b>
  </a>
  END


      $x->go(qw(b))->unwrapContentsKeepingText;                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok -p $x eq <<END;
  <a>
    <b>  DD EE FF  </b>
  </a>
  END

wrapRuns($node, $wrap, @context)

Wrap consecutive runs of children under the specified parent $node that are not already wrapped with $wrap. Returns an array of any wrapping nodes created. Returns () if the specified $node is not in the optional @context.

     Parameter  Description
  1  $node      Node to unwrap
  2  $wrap      Tag of wrapping node
  3  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <a id="i1">
    <b id="i2"/>
    <c id="i3"/>
    <B id="i4">
      <c id="i5"/>
    </B>
    <c id="i6"/>
    <b id="i7"/>
  </a>
  END


    $a->wrapRuns(q(B));                                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a id="i1">
    <B>
      <b id="i2"/>
      <c id="i3"/>
    </B>
    <B id="i4">
      <c id="i5"/>
    </B>
    <B>
      <c id="i6"/>
      <b id="i7"/>
    </B>
  </a>
  END

Contents

The children of each node.

contents($node, @context)

Return a list of all the nodes contained by the specified $node or an empty list if the node is empty or not in the optional @context.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b1"><c id="1"/></b>
    <d id="d1"><c id="2"/></d>
    <e id="e1"><c id="3"/></e>
    <b id="b2"><c id="4"/></b>
    <d id="d2"><c id="5"/></d>
    <e id="e2"><c id="6"/></e>
  </a>
  END


    is_deeply [map{$_->id} $x->contents], [qw(b1 d1 e1 b2 d2 e2)];                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

contentAfter($node, @context)

Return a list of all the sibling nodes following the specified $node or an empty list if the specified $node is last or not in the optional @context.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok 'f g' eq join ' ', map {$_->tag} $x->go(qw(b e))->contentAfter;              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

ca is a synonym for contentAfter.

contentBefore($node, @context)

Return a list of all the sibling nodes preceding the specified $node (in the normal sibling order) or an empty list if the specified $node is last or not in the optional @context.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok 'c d' eq join ' ', map {$_->tag} $x->go(qw(b e))->contentBefore;             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

cb is a synonym for contentBefore.

contentAsTags($node, @context)

Return a string containing the tags of all the child nodes of the specified $node separated by single spaces or the empty string if the node is empty or undef if the node does not match the optional context. Use over to test the sequence of tags with a regular expression.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(q(b))->contentAsTags eq 'c d e f g';                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

contentAsTags2($node, @context)

Return a string containing the tags of all the child nodes of the specified $node separated by two spaces with a single space preceding the first tag and a single space following the last tag or the empty string if the node is empty or undef if the node does not match the optional context. Use over2 to test the sequence of tags with a regular expression. Use over2 to test the sequence of tags with a regular expression.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

    ok $x->go(q(b))->contentAsTags2 eq q( c  d  e  f  g );                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

contentAfterAsTags($node, @context)

Return a string containing the tags of all the sibling nodes following the specified $node separated by single spaces or the empty string if the node is empty or undef if the node does not match the optional context. Use matchAfter to test the sequence of tags with a regular expression.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END

    ok 'f g' eq join ' ', map {$_->tag} $x->go(qw(b e))->contentAfter;


    ok $x->go(qw(b e))->contentAfterAsTags eq 'f g';                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

contentAfterAsTags2($node, @context)

Return a string containing the tags of all the sibling nodes following the specified $node separated by two spaces with a single space preceding the first tag and a single space following the last tag or the empty string if the node is empty or undef if the node does not match the optional context. Use matchAfter2 to test the sequence of tags with a regular expression.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(qw(b e))->contentAfterAsTags2 eq q( f  g );                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

contentBeforeAsTags($node, @context)

Return a string containing the tags of all the sibling nodes preceding the specified $node separated by single spaces or the empty string if the node is empty or undef if the node does not match the optional context. Use matchBefore to test the sequence of tags with a regular expression.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END

    ok 'c d' eq join ' ', map {$_->tag} $x->go(qw(b e))->contentBefore;


    ok $x->go(qw(b e))->contentBeforeAsTags eq 'c d';                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

contentBeforeAsTags2($node, @context)

Return a string containing the tags of all the sibling nodes preceding the specified $node separated by two spaces with a single space preceding the first tag and a single space following the last tag or the empty string if the node is empty or undef if the node does not match the optional context. Use matchBefore2 to test the sequence of tags with a regular expression.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context.

Use the @context parameter to test the context of the specified $node as understood by method at. If a context is supplied and $node is not in this context then this method returns an empty list () immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/><d/><e/><f/><g/>
    </b>
  </a>
  END


    ok $x->go(qw(b e))->contentBeforeAsTags2 eq q( c  d );                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

position($node)

Return the index of the specified $node in the content of the parent of the $node.

     Parameter  Description
  1  $node      Node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END

    ok $a->go(qw(b 1 b))->id == 26;


    ok $a->go(qw(b 1 b))->position == 2;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

index($node)

Return the index of the specified $node in its parent index. Use position to find the position of a node under its parent.

     Parameter  Description
  1  $node      Node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a         id="11">
    <b       id="12">
       <c    id="13"/>
       <d    id="14"/>
       <b    id="15">
          <c id="16"/>
          <d id="17"/>
          <e id="18"/>
          <f id="19"/>
          <g id="20"/>
       </b>
       <f    id="21"/>
       <g    id="22"/>
    </b>
    <b       id="23">
       <c    id="24"/>
       <d    id="25"/>
       <b    id="26">
          <c id="27"/>
          <d id="28"/>
          <e id="29"/>
          <f id="30"/>
          <g id="31"/>
       </b>
       <f    id="32"/>
       <g    id="33"/>
    </b>
  </a>
  END

    ok $a->go(qw(b 1))->id == 23;


    ok $a->go(qw(b 1))->index == 1;                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

present($node, @names)

Return the count of the number of the specified tag types present immediately under a node or a hash {tag} = count for all the tags present under the node if no names are specified.

     Parameter  Description
  1  $node      Node
  2  @names     Possible tags immediately under the node.

Example:

    is_deeply {$a->first->present}, {c=>2, d=>2, e=>1};                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

editText($node, @context)

Return the text of a text $node as an lvalue string reference that can be modified by a regular expression, else as a reference to a dummy string that will be ignored. For a unitary version of this method see: changeText

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a><b>bbbb</b><c/></a>
  END


    $a->by(sub{$_->editText =~ s(bbbb) (BBBB)gs});  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>BBBB</b>
    <c/>
  </a>
  END

isText($node, @context)

Return the specified $node if the specified $node is a text node, optionally in the specified context, else return undef.

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $a->prettyStringCDATA eq <<END;
  <a>
      <b><CDATA> </CDATA></b>
  </a>
  END


    ok $b->first->isText;                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b->first->isText(qw(b a));                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $a = Data::Edit::Xml::new(<<END);
  <a>abcdcba</a>
  END

isFirstText($node, @context)

Return the specified $node if the specified $node is a text node, the first node under its parent and that the parent is optionally in the specified context, else return undef.

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context for parent

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>aaa
      <b>bbb</b>
      ccc
      <d>ddd</d>
      eee
    </a>
  </x>
  END

    my $a = $x->first;

    my ($ta, $b, $tc, $d, $te) = $a->contents;


    ok $ta      ->isFirstText(qw(a x));                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b->first->isFirstText(qw(b a x));                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b->prev ->isFirstText(qw(a x));                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $d->last ->isFirstText(qw(d a x));                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isLastText($node, @context)

Return the specified $node if the specified $node is a text node, the last node under its parent and that the parent is optionally in the specified context, else return undef.

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context for parent

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
    <a>aaa
      <b>bbb</b>
      ccc
      <d>ddd</d>
      eee
    </a>
  </x>
  END


    ok $d->next ->isLastText (qw(a x));                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $d->last ->isLastText (qw(d a x));                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $te      ->isLastText (qw(a x));                                             # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

matchTree($node, @match)

Return a list of nodes that match the specified tree of match expressions, else () if one or more match expressions fail to match nodes in the tree below the specified start node. A match expression consists of [parent node tag, [match expressions to be matched by children of parent]|tags of child nodes to match starting at the first node]. Match expressions for a single item do need to be surrounded with [] and can be merged into their predecessor. The outermost match expression should not be enclosed in [].

     Parameter  Description
  1  $node      Node to start matching from
  2  @match     Tree of match expressions.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
    <e>
      <f>
        <g/>
      </f>
    </e>
  </a>
  END
    my ($c, $d, $b, $g, $f, $e) = $a->byList;


    is_deeply [$b, $c, $d], [$b->matchTree(qw(b c d))];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$e, $f, $g], [$e->matchTree(qr(\Ae\Z), [qw(f g)])];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$c],         [$c->matchTree(qw(c))];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply [$a, $b, $c, $d, $e, $f, $g],

              [$a->matchTree({a=>1}, [qw(b c d)], [qw(e), [qw(f g)]])];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }

matchesText($node, $re, @context)

Returns an array of regular expression matches in the text of the specified $node if it is text node and it matches the specified regular expression and optionally has the specified context otherwise returns an empty array.

     Parameter  Description
  1  $node      Node to test
  2  $re        Regular expression
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>CDECD</c>
    </b>
  </a>
  END

    my $c = $x->go(qw(b c))->first;


    ok !$c->matchesText(qr(\AD));                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $c->matchesText(qr(\AC), qw(c b a));                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$c->matchesText(qr(\AD), qw(c b a));                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    is_deeply [qw(E)], [$c->matchesText(qr(CD(.)CD))];                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isBlankText($node, @context)

Return the specified $node if the specified $node is a text node, optionally in the specified context, and contains nothing other than white space else return undef. See also: isAllBlankText

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok $a->prettyStringCDATA eq <<END;
  <a>
      <b><CDATA> </CDATA></b>
  </a>
  END


    ok $b->first->isBlankText;                                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isAllBlankText($node, @context)

Return the specified $node if the specified $node, optionally in the specified context, does not contain anything or if it does contain something it is all white space else return undef. See also: bitsNodeTextBlank

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <z/>
      </c>
    </b>
    <d/>
  </a>
  END

    $a->by(sub{$_->replaceWithBlank(qw(z))});

    my ($b, $c, $d) = $a->firstBy(qw(b c d));


    ok  $c->isAllBlankText;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $c->isAllBlankText(qw(c b a));                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$c->isAllBlankText(qw(c a));                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

isOnlyChildBlankText($node, @context)

Return the specified $node if it is a blank text node and an only child else return undef.

     Parameter  Description
  1  $node      Node to test
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a>aaaa</a>));
    $a->first->text = q( );
    ok  $a->prettyStringCDATA eq qq(<a><CDATA> </CDATA></a>
);

    ok  $a->first->isOnlyChildBlankText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$a->isOnlyChildBlankText;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }

  if (1)
   {my $a = Data::Edit::Xml::new(q(<a/>));
    my $b = $a->new(q(<b/>));
    ok -p $a eq qq(<a/>
);
    ok -p $b eq qq(<b/>
);
   }

bitsNodeTextBlank($node)

Return a bit string that shows if there are any non text nodes, text nodes or blank text nodes under a node. An empty string is returned if there are no child nodes.

     Parameter  Description
  1  $node      Node to test.

Example:

    ok $x->prettyStringCDATA eq <<END;
  <a>
      <b>
          <C/>
      </b>
      <c>
          <D/>
  <CDATA>
       E
      </CDATA>
      </c>
      <d>
          <F/>
  <CDATA> </CDATA>
          <H/>
      </d>
      <e/>
  </a>
  END

    ok '100' eq -B $x;

    ok '100' eq -B $x->go(q(b));

    ok '110' eq -B $x->go(q(c));

    ok '111' eq -B $x->go(q(d));

    ok !-B $x->go(qw(e));

Number

Number the nodes of a parse tree so that they can be easily retrieved by number - either by a person reading the source Xml or programmatically.

findByNumber($node, $number)

Find the node with the specified number as made visible by prettyStringNumbered in the parse tree containing the specified $node and return the found node or undef if no such node exists.

     Parameter  Description
  1  $node      Node in the parse tree to search
  2  $number    Number of the node required.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/></b><d><e/></d></a>
  END

    $a->numberTree;
    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3"/>
    </b>
    <d id="4">
      <e id="5"/>
    </d>
  </a>
  END

    ok -t $a->findByNumber_4 eq q(d);
    ok    $a->findByNumber_3__up__number == 2;
   }

    $a->numberTree;

    ok $a->prettyStringNumbered eq <<END;
  <a id="1">
    <b id="2">
      <A id="3"/>
      <B id="4"/>
    </b>
    <c id="5">
      <C id="6"/>
      <D id="7"/>
    </c>
  </a>
  END


    ok q(D) eq -t $a->findByNumber(7);                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

findByNumbers($node, @numbers)

Find the nodes with the specified numbers as made visible by prettyStringNumbered in the parse tree containing the specified $node and return the found nodes in a list with undef for nodes that do not exist.

     Parameter  Description
  1  $node      Node in the parse tree to search
  2  @numbers   Numbers of the nodes required.

Example:

    $a->numberTree;

    ok $a->prettyStringNumbered eq <<END;
  <a id="1">
    <b id="2">
      <A id="3"/>
      <B id="4"/>
    </b>
    <c id="5">
      <C id="6"/>
      <D id="7"/>
    </c>
  </a>
  END


    is_deeply [map {-t $_} $a->findByNumbers(1..3)], [qw(a b A)];                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

numberTree($node)

Number the nodes in a parse tree in pre-order so they are numbered in the same sequence that they appear in the source. You can see the numbers by printing the tree with prettyStringNumbered. Nodes can be found using findByNumber. This method differs from forestNumberTrees in that avoids overwriting the id= attribute of each node by using a system attribute instead; this system attribute can then be made visible on the id attribute of each node by printing the parse tree with prettyStringNumbered.

     Parameter  Description
  1  $node      Node

Example:

    $a->numberTree;                                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="42" match="mm"/>
    </b>
    <d id="4">
      <e id="5"/>
    </d>
  </a>
  END

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/></b><d><e/></d></a>
  END


    $a->numberTree;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3"/>
    </b>
    <d id="4">
      <e id="5"/>
    </d>
  </a>
  END

    ok -t $a->findByNumber_4 eq q(d);
    ok    $a->findByNumber_3__up__number == 2;
   }

indexIds($node)

Return a map of the ids at and below the specified $node.

     Parameter  Description
  1  $node      Node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a id="A">
    <b id="B">
      <c id="C"/>
      <d id="D">
        <e id="E"/>
        <f id="F"/>
      </d>
    </b>
  </a>
  END


    my $i = $a->indexIds;                                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $i->{C}->tag eq q(c);

    ok $i->{E}->tag eq q(e);

numberTreesJustIds($node, $prefix)

Number the ids of the nodes in a parse tree in pre-order so they are numbered in the same sequence that they appear in the source. You can see the numbers by printing the tree with prettyStringNumbered(). This method differs from numberTree in that only non text nodes without ids are numbered. The number applied to each node consists of the concatenation of the specified prefix, an underscore and a number that is unique within the specifed parse tree. Consequently the ids across several trees trees can be made unique by supplying different prefixes for each tree. Nodes can be found using findByNumber. Returns the specified $node.

     Parameter  Description
  1  $node      Node
  2  $prefix    Prefix for each id at and under the specified B<$node>

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>A
    <b id="bb">B
      <c/>
      <d>D
        <e id="ee"/>
          E
        <f/>
          F
      </d>
      G
    </b>
    H
  </a>
  END


    $a->numberTreesJustIds(q(T));                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $A = Data::Edit::Xml::new(<<END);
  <a id="T1">A
    <b id="bb">B
      <c id="T2"/>
      <d id="T3">D
        <e id="ee"/>
          E
        <f id="T4"/>
          F
      </d>
      G
    </b>
    H
  </a>
  END

    ok -p $a eq -p $A;

Forest Numbers

Number the nodes of several parse trees so that they can be easily retrieved by forest number - either by a person reading the source Xml or programmatically.

forestNumberTrees($node, $prefix)

Number the ids of the nodes in a parse tree in pre-order so they are numbered in the same sequence that they appear in the source. You can see the numbers by printing the tree with prettyString. This method differs from numberTree in that only non text nodes are numbered and nodes with existing id= attributes have the value of their id= attribute transferred to a label. The number applied to each node consists of the concatenation of the specified tree number, an underscore and a number that is unique within the specified parse tree. Consequently the ids across several trees can be made unique by supplying a different tree number for each tree. Nodes can be found subsequently using findByForestNumber. Returns the specified $node.

     Parameter  Description
  1  $node      Node in parse tree to be numbered
  2  $prefix    Tree number

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b">
      <c/>
    </b>
    <b id="B">
      <d/>
      <e/>
    </b>
  </a>
  END

    my $e = $a->go(qw(b -1 e));


    $e->forestNumberTrees(1);                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a id="1_1">
    <b id="1_2">
      <c id="1_3"/>
    </b>
    <b id="1_4">
      <d id="1_5"/>
      <e id="1_6"/>
    </b>
  </a>
  END

findByForestNumber($node, $tree, $id)

Find the node with the specified forest number as made visible on the id attribute by prettyStringNumbered in the parse tree containing the specified $node and return the found node or undef if no such node exists.

     Parameter  Description
  1  $node      Node in the parse tree to search
  2  $tree      Forest number
  3  $id        Id number of the node required.

Example:

    ok -p $a eq <<END;
  <a id="1_1">
    <b id="1_2">
      <c id="1_3"/>
    </b>
    <b id="1_4">
      <d id="1_5"/>
      <e id="1_6"/>
    </b>
  </a>
  END


    my $B = $e->findByForestNumber(1, 4);                                           # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply [$B->getLabels], ["B"];

Order

Check the order and relative position of nodes in a parse tree.

above($first, $second, @context)

Return the first node if the first node is above the second node optionally checking that the first node is in the specified context otherwise return undef

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    ok $b->id eq 'b1';

    ok $e->id eq "e1";

    ok $E->id eq "e2";


    ok  $b->above($e);                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$E->above($e);                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

abovePath($first, $second)

Return the nodes along the path from the first node down to the second node when the first node is above the second node else return ().

     Parameter  Description
  1  $first     First node
  2  $second    Second node

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    my ($a, $b, $c, $d, $e) = $x->firstDown(@tags);


    is_deeply [$b, $d, $e], [$b->abovePath($e)];                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    is_deeply [],   [$c->abovePath($d)];                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

below($first, $second, @context)

Return the first node if the first node is below the second node optionally checking that the first node is in the specified context otherwise return undef

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    ok $d->id eq 'd1';

    ok $e->id eq "e1";


    ok !$d->below($e);                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

belowPath($first, $second)

Return the nodes along the path from the first node up to the second node when the first node is below the second node else return ().

     Parameter  Description
  1  $first     First node
  2  $second    Second node

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    my ($a, $b, $c, $d, $e) = $x->firstDown(@tags);


    is_deeply [$e, $d, $b], [$e->belowPath($b)];                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    is_deeply [$c], [$c->belowPath($c)];                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

after($first, $second, @context)

Return the first node if it occurs after the second node in the parse tree optionally checking that the first node is in the specified context or else undef if the node is above, below or before the target.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    ok $c->id eq 'c1';

    ok $e->id eq "e1";


    ok $e->after($c);                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

before($first, $second, @context)

Return the first node if it occurs before the second node in the parse tree optionally checking that the first node is in the specified context or else undef if the node is above, below or before the target.

     Parameter  Description
  1  $first     First node
  2  $second    Second node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    ok $e->id eq "e1";

    ok $E->id eq "e2";


    ok $e->before($E);                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

disordered($node, @nodes)

Return the first node that is out of the specified order when performing a pre-ordered traversal of the parse tree.

     Parameter  Description
  1  $node      Node
  2  @nodes     Following nodes.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    ok $b->id eq 'b1';

    ok $c->id eq 'c1';

    ok $d->id eq 'd1';

    ok $e->id eq "e1";


    ok  $e->disordered($c        )->id eq "c1";                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $b->disordered($c, $e, $d)->id eq "d1";                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$c->disordered($e);                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

commonAncestor($node, @nodes)

Find the most recent common ancestor of the specified nodes or undef if there is no common ancestor.

     Parameter  Description
  1  $node      Node
  2  @nodes     @nodes

Example:

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="3">
        <e id="4"/>
      </c>
      <d id="5">
        <e id="6"/>
      </d>
      <c id="7">
        <d id="8">
          <e id="9"/>
        </d>
      </c>
      <d id="10">
        <e id="11"/>
      </d>
      <c id="12">
        <d id="13">
          <e id="14"/>
        </d>
      </c>
    </b>
  </a>
  END

     {my ($b, $e, @n) = $a->findByNumbers(2, 4, 6, 9);


      ok $e == $e->commonAncestor;                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



      ok $e == $e->commonAncestor($e);                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



      ok $b == $e->commonAncestor($b);                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



      ok $b == $e->commonAncestor(@n);                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

commonAdjacentAncestors($first, $second)

Given two nodes, find a pair of adjacent ancestral siblings if such a pair exists else return ().

     Parameter  Description
  1  $first     First node
  2  $second    Second node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    is_deeply [$d->commonAdjacentAncestors($C)], [$b, $B];                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

ordered($node, @nodes)

Return the first node if the specified nodes are all in order when performing a pre-ordered traversal of the parse tree else return undef.

     Parameter  Description
  1  $node      Node
  2  @nodes     Following nodes.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a       id='a1'>
    <b     id='b1'>
      <c   id='c1'/>
      <c   id='c2'/>
      <d   id='d1'>
        <e id='e1'/>
      </d>
      <c   id='c3'/>
      <c   id='c4'/>
      <d   id='d2'>
        <e id='e2'/>
      </d>
      <c   id='c5'/>
      <c   id='c6'/>
    </b>
  </a>
  END

    ok $e->id eq "e1";

    ok $E->id eq "e2";


    ok  $e->ordered($E);                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$E->ordered($e);                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $e->ordered($e);                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok  $e->ordered;                                                                # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Patching

Analyze two similar parse trees and create a patch that transforms the first parse tree into the second as long as each tree has the same tag and id structure with each id being unique.

createPatch($a, $A)

Create a patch that moves the source parse tree to the target parse tree node as long as they have the same tag and id structure with each id being unique.

     Parameter  Description
  1  $a         Source parse tree
  2  $A         Target parse tree

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>Aaaaa
    <b b1="b1" b2="b2">Bbbbb
      <c c1="c1" />Ccccc
      <d d1="d1" >Ddddd
        <e  e1="e1" />
          Eeeee
        <f  f1="f1" />
          Fffff
      </d>
      Ggggg
    </b>
    Hhhhhh
  </a>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>AaaAaaA
    <b b1="b1" b3="B3">BbbBbbB
      <c c1="C1" />Ccccc
      <d d2="D2" >DddDddD
        <e  e3="E3" />
          EeeEeeE
        <f  f1="F1" />
          FffFffF
      </d>
      GggGggG
    </b>
    Hhhhhh
  </a>
  END

    $a->numberTreesJustIds(q(a));

    $A->numberTreesJustIds(q(a));


    my $patches = $a->createPatch($A);                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    $patches->install($a);

    ok !$a->diff  ($A);

    ok  $a->equals($A);

Data::Edit::Xml::Patch::install($patches, $a)

Replay a patch created by createPatch against a parse tree that has the same tag and id structure with each id being unique.

     Parameter  Description
  1  $patches   Patch
  2  $a         Parse tree

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>Aaaaa
    <b b1="b1" b2="b2">Bbbbb
      <c c1="c1" />Ccccc
      <d d1="d1" >Ddddd
        <e  e1="e1" />
          Eeeee
        <f  f1="f1" />
          Fffff
      </d>
      Ggggg
    </b>
    Hhhhhh
  </a>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>AaaAaaA
    <b b1="b1" b3="B3">BbbBbbB
      <c c1="C1" />Ccccc
      <d d2="D2" >DddDddD
        <e  e3="E3" />
          EeeEeeE
        <f  f1="F1" />
          FffFffF
      </d>
      GggGggG
    </b>
    Hhhhhh
  </a>
  END

    $a->numberTreesJustIds(q(a));

    $A->numberTreesJustIds(q(a));

    my $patches = $a->createPatch($A);

    $patches->install($a);

    ok !$a->diff  ($A);

    ok  $a->equals($A);

Propogating

Propagate parent node attributes through a parse tree.

propagate($tree, $tag, @context)

Propagate new attributes from nodes that match the specified tag to all their child nodes, then unwrap all the nodes that match the specified tag. Return the specified parse tree.

     Parameter  Description
  1  $tree      Parse tree
  2  $tag       Tag of nodes whose attributes are to be propagated
  3  @context   Optional context for parse tree

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b b="B">
      <b c="C">
        <c/>
        <b d="D">
          <d/>
          <b e="E">
            <e/>
          </b>
        </b>
      </b>
    </b>
  </a>
  END


    $a->propagate(q(b));                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <c b="B" c="C"/>
    <d b="B" c="C" d="D"/>
    <e b="B" c="C" d="D" e="E"/>
  </a>
  END

Table of Contents

Analyze and generate tables of contents.

tocNumbers($node, @match)

Table of Contents number the nodes in a parse tree.

     Parameter  Description
  1  $node      Node
  2  @match     Optional list of tags to descend into else all tags will be descended into

Example:

    ok $a->prettyStringNumbered eq <<END;
  <a id="1">
    <b id="2">
      <A id="3"/>
      <B id="4"/>
    </b>
    <c id="5">
      <C id="6"/>
      <D id="7"/>
    </c>
  </a>
  END


      my $t = $a->tocNumbers();                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      is_deeply {map {$_=>$t->{$_}->tag} keys %$t},

       {"1"  =>"b",

        "1 1"=>"A",

        "1 2"=>"B",

        "2"  =>"c",

        "2 1"=> "C",

        "2 2"=>"D"

       }

Labels

Label nodes so that they can be cross referenced and linked by Data::Edit::Xml::Lint

addLabels($node, @labels)

Add the named labels to the specified $node and return the number of labels added. Labels that are not defined will be ignored.

     Parameter  Description
  1  $node      Node in parse tree
  2  @labels    Names of labels to add.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b><c/></b></a>';

    my $b = $x->go(q(b));

    ok $b->countLabels == 0;


    $b->addLabels(1..2);                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    $b->addLabels(3..4);                                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c/></b></a>';

countLabels($node)

Return the count of the number of labels at a node.

     Parameter  Description
  1  $node      Node in parse tree.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b><c/></b></a>';

    my $b = $x->go(q(b));


    ok $b->countLabels == 0;                                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    $b->addLabels(1..2);

    $b->addLabels(3..4);

    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c/></b></a>';


    ok $b->countLabels == 4;                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

labelsInTree($tree)

Return a hash of all the labels in a tree

     Parameter  Description
  1  $tree      Parse tree.

Example:

    ok -p (new $A->stringExtendingIdsWithLabels) eq <<END;
  <a id="aa, a, a5">
    <b id="bb, b, b2">
      <c id="cc, c, c1"/>
    </b>
    <b id="B, b4">
      <c id="C, c3"/>
    </b>
  </a>
  END


    is_deeply [sort keys %{$A->labelsInTree}],                                      # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ["B", "C", "a", "a5", "b", "b2", "b4", "c", "c1", "c3"];

getLabels($node)

Return the names of all the labels set on a node.

     Parameter  Description
  1  $node      Node in parse tree.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b><c/></b></a>';

    my $b = $x->go(q(b));

    ok $b->countLabels == 0;

    $b->addLabels(1..2);

    $b->addLabels(3..4);

    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c/></b></a>';


    is_deeply [1..4], [$b->getLabels];                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

deleteLabels($node, @labels)

Delete the specified labels in the specified $node or all labels if no labels have are specified and return that node.

     Parameter  Description
  1  $node      Node in parse tree
  2  @labels    Names of the labels to be deleted

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c id="1, 2, 3, 4"/></b></a>';


    $b->deleteLabels(1,4) for 1..2;                                                 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->stringReplacingIdsWithLabels eq '<a><b id="2, 3"><c id="1, 2, 3, 4"/></b></a>';

copyLabels($source, $target)

Copy all the labels from the source node to the target node and return the source node.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c/></b></a>';


    $b->copyLabels($c) for 1..2;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->stringReplacingIdsWithLabels eq '<a><b id="1, 2, 3, 4"><c id="1, 2, 3, 4"/></b></a>';

moveLabels($source, $target)

Move all the labels from the source node to the target node and return the source node.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node.

Example:

    ok $x->stringReplacingIdsWithLabels eq '<a><b id="2, 3"><c id="1, 2, 3, 4"/></b></a>';


    $b->moveLabels($c) for 1..2;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $x->stringReplacingIdsWithLabels eq '<a><b><c id="1, 2, 3, 4"/></b></a>';

copyLabelsAndIdsInTree($source, $target)

Copy all the labels and ids in the source parse tree to the matching nodes in the target parse tree. Nodes are matched via path. Return the number of labels and ids copied.

     Parameter  Description
  1  $source    Source node
  2  $target    Target node.

Example:

    ok -p (new $a->stringExtendingIdsWithLabels) eq <<END;
  <a id="a, a5">
    <b id="b, b2">
      <c id="c, c1"/>
    </b>
    <b id="B, b4">
      <c id="C, c3"/>
    </b>
  </a>
  END

    ok -p (new $A->stringExtendingIdsWithLabels) eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"/>
    </b>
    <b>
      <c/>
    </b>
  </a>
  END


    ok $a->copyLabelsAndIdsInTree($A) == 10;                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p (new $A->stringExtendingIdsWithLabels) eq <<END;
  <a id="aa, a, a5">
    <b id="bb, b, b2">
      <c id="cc, c, c1"/>
    </b>
    <b id="B, b4">
      <c id="C, c3"/>
    </b>
  </a>
  END

giveEveryIdAGuid($tree, $genGuid)

Give a guid to every node in the specified $tree that has an id attribute, saving any existing id attribute as a label, and return the count of the number of such replacements made.

     Parameter  Description
  1  $tree      Tree
  2  $genGuid   A sub that accepts a number and a node and returns a new Guid each time it is called

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a id="a">
    <b id="b">
      <c id="c"/>
    </b>
    <d/>
  </a>
  END
    my $n  =0;

    $a->giveEveryIdAGuid(sub  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my ($n, $o) = @_;
      qq(GUID-$n)
     });

    ok -p $a eq <<END;
  <a id="GUID-3">
    <b id="GUID-2">
      <c id="GUID-1"/>
    </b>
    <d/>
  </a>
  END

   ok $a->stringReplacingIdsWithLabels eq q(<a id="a"><b id="b"><c id="c"/></b><d/></a>);
   ok $a->stringExtendingIdsWithLabels eq q(<a id="GUID-3, a"><b id="GUID-2, b"><c id="GUID-1, c"/></b><d/></a>);

   }

createGuidId($node, @context)

Create an id for the specified $node in the optional @context from the md5Sum of its content moving any existing id to the labels associated with the $node and return the existing $node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      c
    </b>
  </a>
  END


    ok $a->createGuidId->id eq q(GUID-390bf05d-8f56-71cc-6a47-71834840d695);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Operators

Operator access to methods use the assign versions to avoid 'useless use of operator in void context' messages. Use the non assign versions to return the results of the underlying method call. Thus '/' returns the wrapping node, whilst '/=' does not. Assign operators always return their left hand side even though the corresponding method usually returns the modification on the right.

opString($node, $op)

-A: printNode

-B: bitsNodeTextBlank

-b: isAllBlankText

-C: stringContent

-c: context

-d: depth

-e: prettyStringEnd

-f: first node

-g: createGuidId

-k: createGuidId

-l: last node

-M: stringAsMd5Sum

-O: contentAsTags2

-o: contentAsTags

-p: prettyString

-R: requiredCleanup

-r: stringTagsAndText

-S: printStack

-s: string

-T: isText

-t: tag

-u: unwrap

-W: id

-w: stringQuoted

-X: prettyStringDitaHeaders

-x: cut

-z: prettyStringNumbered.

     Parameter  Description
  1  $node      Node
  2  $op        Monadic operator.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b><c>ccc</c></b>
    <d><e>eee</e></d>
  </a>
  END

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    my ($c, $b, $e, $d) = $a->byList;

    ok $c->printNode eq q(c id="42" match="mm");

    ok -A $c eq q(c id="42" match="mm");

    ok -b $e;

    ok -c $e eq q(e d a);

    ok -f $b eq $c;

    ok -l $a eq $d;

    ok -O $a, q( b  d );

    ok -o $a, q(b d);

    ok -w $a eq q('<a><b><c id="42" match="mm"/></b><d><e/></d></a>');

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    ok -s $a eq '<a><b><c id="42" match="mm"/></b><d><e/></d></a>';

    ok -t $a eq 'a';

    $a->numberTree;

    ok -z $a eq <<END;
  <a id="1">
    <b id="2">
      <c id="42" match="mm"/>
    </b>
    <d id="4">
      <e id="5"/>
    </d>
  </a>
  END

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <concept/>
  END

    ok $a->ditaPrettyPrintWithHeaders eq <<END;
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd" []>
  <concept/>
  END

   }

opContents($node)

@{} : nodes immediately below a node.

     Parameter  Description
  1  $node      Node.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b><c>ccc</c></b>
    <d><e>eee</e></d>
  </a>
  END

    my ($b, $d) =  @$a;

    ok -c $b eq q(b a);

    my ($c)     =  @$b;

    ok -c $c eq q(c b a);

opAt($node, $context)

<= : Check that a node is in the context specified by the referenced array of words.

     Parameter  Description
  1  $node      Node
  2  $context   Reference to array of words specifying the parents of the desired node.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    ok (($a >= [qw(d e)]) <= [qw(e d a)]);

opNew($node, $text)

** : create a new node from the text on the right hand side: if the text contains a non word character \W the node will be create as text, else it will be created as a tag

     Parameter  Description
  1  $node      Node
  2  $text      Name node of node to create or text of new text element

Example:

    my $a = Data::Edit::Xml::new("<a/>");

    my $b = $a ** q(b);

    ok -s $b eq "<b/>";

opPutFirst($node, $text)

>> : put a node or string first under a node and return the new node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place first under the node.

Example:

    ok -p $a eq <<END;
  <a/>
  END

    my $f = $a >> qq(first);

    ok -p $a eq <<END;
  <a>
    <first/>
  </a>
  END

opPutFirstAssign($node, $text)

>>= : put a node or string first under a node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place first under the node.

Example:

    ok -p $a eq <<END;
  <a/>
  END

    $a >>= qq(first);

    ok -p $a eq <<END;
  <a>
    <first/>
  </a>
  END

opPutLast($node, $text)

<< : put a node or string last under a node and return the new node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place last under the node.

Example:

    ok -p $a eq <<END;
  <a>
    <first/>
  </a>
  END

    my $l = $a << qq(last);

    ok -p $a eq <<END;
  <a>
    <first/>
    <last/>
  </a>
  END

opPutLastAssign($node, $text)

<<= : put a node or string last under a node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place last under the node.

Example:

    ok -p $a eq <<END;
  <a>
    <first/>
  </a>
  END

    $a <<= qq(last);

    ok -p $a eq <<END;
  <a>
    <first/>
    <last/>
  </a>
  END

opPutNext($node, $text)

> + : put a node or string after the specified $node and return the new node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place after the first node.

Example:

    ok -p $a eq <<END;
  <a>
    <first/>
    <last/>
  </a>
  END

    $f += qq(next);

    ok -p $a eq <<END;
  <a>
    <first/>
    <next/>
    <last/>
  </a>
  END

opPutNextAssign($node, $text)

+= : put a node or string after the specified $node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place after the first node.

Example:

    ok -p $a eq <<END;
  <a>
    <first/>
    <last/>
  </a>
  END

    my $f = -f $a;

    $f += qq(next);

    ok -p $a eq <<END;
  <a>
    <first/>
    <next/>
    <last/>
  </a>
  END

opPutPrev($node, $text)

< - : put a node or string before the specified $node and return the new node.

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place before the first node.

Example:

    ok -p $a eq <<END;
  <a>
    <first/>
    <next/>
    <last/>
  </a>
  END

    $l -= qq(prev);

    ok -p $a eq <<END;
  <a>
    <first/>
    <next/>
    <prev/>
    <last/>
  </a>
  END

opPutPrevAssign($node, $text)

-= : put a node or string before the specified $node,

     Parameter  Description
  1  $node      Node
  2  $text      Node or text to place before the first node.

Example:

    ok -p $a eq <<END;
  <a>
    <first/>
    <next/>
    <last/>
  </a>
  END

    my $l = -l $a;

    $l -= qq(prev);

    ok -p $a eq <<END;
  <a>
    <first/>
    <next/>
    <prev/>
    <last/>
  </a>
  END

opBy($node, $code)

x= : Traverse a parse tree in post-order.

     Parameter  Description
  1  $node      Parse tree
  2  $code      Code to execute against each node.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

     {my $s; $a x= sub{$s .= -t $_}; ok $s eq "cbeda"

opGo($node, $go)

>= : Search for a node via a specification provided as a reference to an array of words each number. Each word represents a tag name, each number the index of the previous tag or zero by default.

     Parameter  Description
  1  $node      Node
  2  $go        Reference to an array of search parameters.

Example:

    ok -p $a eq <<END;
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END

    ok (($a >= [qw(d e)]) <= [qw(e d a)]);

opAttr($node, $attr)

% : Get the value of an attribute of the specified $node.

     Parameter  Description
  1  $node      Node
  2  $attr      Reference to an array of words and numbers specifying the node to search for.

Example:

    my $a = Data::Edit::Xml::new('<a number="1"/>');

    ok $a %  qq(number) == 1;

opWrapWith($node, $tag)

/ : Wrap node with a tag, returning the wrapping node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag.

Example:

    my $c = Data::Edit::Xml::new("<c/>");

    my $b = $c / qq(b);

    ok -s $b eq "<b><c/></b>";

    my $a = $b / qq(a);

    ok -s $a eq "<a><b><c/></b></a>";

opWrapContentWith($node, $tag)

* : Wrap content with a tag, returning the wrapping node.

     Parameter  Description
  1  $node      Node
  2  $tag       Tag.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my ($c, $d, $b) = $a->byList;

    $b *= q(B);

    ok -p $a eq <<END;
  <a>
    <b>
      <B>
        <c/>
        <d/>
      </B>
    </b>
  </a>
  END

opCut($node)

-- : Cut out a node.

     Parameter  Description
  1  $node      Node.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a>
    <b><c/></b>
  </a>
  END

    my $b = $x >= qq(b);

     --$b;

    ok -s $x eq "<a/>";

    ok -s $b eq "<b><c/></b>";

opUnwrap($node)

++ : Unwrap a node.

     Parameter  Description
  1  $node      Node.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
      <d/>
    </b>
  </a>
  END

    my ($c, $d, $b) = $a->byList;

    $b++;

    ok -p $a eq <<END;
  <a>
    <c/>
    <d/>
  </a>
  END

Reuse

Identify common components that can be reused

subMd5Tree($node)

Return the md5 sum of the stringContent of the parse tree.

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>bb</b>
   <b><c>bb</c></b>
   <d>dd</d>
   <d>dd</d>
  </a>
  END


    is_deeply [$a->first->subMd5Tree], [q(21ad0bd836b90d08f4cf640b4c298e7c), q(bb)];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply subMd5($a, map {$_=>1} qw(b c)),
     {b => {"21ad0bd836b90d08f4cf640b4c298e7c" => {    bb      => 1},
            "95c1bde7f88ced04c1b1fbcab120ed96" => {"<c>bb</c>" => 1},
            },
      c => {"21ad0bd836b90d08f4cf640b4c298e7c" => {    bb      => 1}},
     };
  # owf(q(/home/phil/z/z/z/out.xml), dump(subMd5($a, map{$_=>1} qw(b c))));

subMd5($node, %tags)

Return a hash {md5 sum of parse tree}{string representation of sub tree}++ to locate common parse trees under $node that could be included via a conref. md5 sums are only calculated for nodes whose tags match the keys of the $tags hash that have truthful values. The attributes of the root node of each sub tree are ignored in the computation as they can be supplied by the conreffing element.

     Parameter  Description
  1  $node      Node
  2  %tags      Hash of acceptable tags.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
   <b>bb</b>
   <b><c>bb</c></b>
   <d>dd</d>
   <d>dd</d>
  </a>
  END

    is_deeply [$a->first->subMd5Tree], [q(21ad0bd836b90d08f4cf640b4c298e7c), q(bb)];


    is_deeply subMd5($a, map {$_=>1} qw(b c)),  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {b => {"21ad0bd836b90d08f4cf640b4c298e7c" => {    bb      => 1},
            "95c1bde7f88ced04c1b1fbcab120ed96" => {"<c>bb</c>" => 1},
            },
      c => {"21ad0bd836b90d08f4cf640b4c298e7c" => {    bb      => 1}},
     };

  # owf(q(/home/phil/z/z/z/out.xml), dump(subMd5($a, map{$_=>1} qw(b c))));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Statistics

Statistics describing the parse tree.

count($node, @names)

Return the count of the number of instances of the specified tags under the specified $node, either by tag in array context or in total in scalar context.

     Parameter  Description
  1  $node      Node
  2  @names     Possible tags immediately under the node.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a>

  </a>
  END


    ok $x->count == 0;                                                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

countTags($node)

Count the number of tags in a parse tree.

     Parameter  Description
  1  $node      Parse tree.

Example:

      ok -p $a eq <<END;
  <a id="aa">
    <b id="bb">
      <c id="cc"/>
    </b>
  </a>
  END


      ok $a->countTags == 3;                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

countTagNames($node, @exclude)

Return a reference to a hash showing the number of instances of each tag on and below the specified $node excluding any tags named in @exclude.

     Parameter  Description
  1  $node      Node
  2  @exclude   Tags to exclude from the count

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a A="A1" B="B1" C="C1">
    <b  B="B1" C="C1">
      <c  C="C1">
      </c>
      <c/>
    </b>
    <b  B="B2">
      <c C="C2"/>
    </b>
  </a>
  END


    is_deeply $x->countTagNames,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {a => 1, b => 2, c => 3};

    is_deeply $x->countAttrNames,
     {A => 1, B => 3, C => 4};

    is_deeply $x->countAttrValues,
     {A1 => 1, B1 => 2, B2 => 1, C1 => 3, C2 => 1};

    is_deeply $x->countAttrNamesAndValues,
     {A => {A1 => 1}, B => {B1 => 2, B2 => 1}, C => {C1 => 3, C2 => 1}};

countNonEmptyTags($node, @exclude)

Return a reference to a hash showing the number of instances of each non empty tag on and below the specified $node excluding any tags named in @exclude.

     Parameter  Description
  1  $node      Node
  2  @exclude   Tags to exclude from the count

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
  </a>
  END


    is_deeply $a->countNonEmptyTags(qw(c)), {a=>1, b=>1};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply $a->go_b->countNonEmptyTags,  {b=>1, c=>1};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

countTexts($node)

Return a reference to a hash showing the incidence of texts on and below the specified $node.

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <concept>
    <title/>
    <conbody/>
  </concept>
  END


    is_deeply $a->countTexts, {};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

countAttrNames($node, $count)

Return a reference to a hash showing the number of instances of each attribute on and below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $count     Attribute count so far

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a A="A1" B="B1" C="C1">
    <b  B="B1" C="C1">
      <c  C="C1">
      </c>
      <c/>
    </b>
    <b  B="B2">
      <c C="C2"/>
    </b>
  </a>
  END

    is_deeply $x->countTagNames,
     {a => 1, b => 2, c => 3};


    is_deeply $x->countAttrNames,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {A => 1, B => 3, C => 4};

    is_deeply $x->countAttrValues,
     {A1 => 1, B1 => 2, B2 => 1, C1 => 3, C2 => 1};

    is_deeply $x->countAttrNamesAndValues,
     {A => {A1 => 1}, B => {B1 => 2, B2 => 1}, C => {C1 => 3, C2 => 1}};

countAttrNamesOnTagExcluding($node, @attr)

Count the number of attributes owned by the specified $node that are not in the specified list.

     Parameter  Description
  1  $node      Node
  2  @attr      Attributes to ignore

Example:

   {my $a = Data::Edit::Xml::new(q(<a a="1" b="2" c="3" d="4" e="5"/>));

countAttrValues($node, $count)

Return a reference to a hash showing the number of instances of each attribute value on and below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $count     Count of attributes so far.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a A="A1" B="B1" C="C1">
    <b  B="B1" C="C1">
      <c  C="C1">
      </c>
      <c/>
    </b>
    <b  B="B2">
      <c C="C2"/>
    </b>
  </a>
  END

    is_deeply $x->countTagNames,
     {a => 1, b => 2, c => 3};

    is_deeply $x->countAttrNames,
     {A => 1, B => 3, C => 4};


    is_deeply $x->countAttrValues,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {A1 => 1, B1 => 2, B2 => 1, C1 => 3, C2 => 1};

    is_deeply $x->countAttrNamesAndValues,
     {A => {A1 => 1}, B => {B1 => 2, B2 => 1}, C => {C1 => 3, C2 => 1}};

countAttrNamesAndValues($node, $count)

Return a reference to a hash showing the number of instances of each attribute name and value on and below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $count     Count of attributes so far.

Example:

    my $x = Data::Edit::Xml::new(<<END);
  <a A="A1" B="B1" C="C1">
    <b  B="B1" C="C1">
      <c  C="C1">
      </c>
      <c/>
    </b>
    <b  B="B2">
      <c C="C2"/>
    </b>
  </a>
  END

    is_deeply $x->countTagNames,
     {a => 1, b => 2, c => 3};

    is_deeply $x->countAttrNames,
     {A => 1, B => 3, C => 4};

    is_deeply $x->countAttrValues,
     {A1 => 1, B1 => 2, B2 => 1, C1 => 3, C2 => 1};


    is_deeply $x->countAttrNamesAndValues,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {A => {A1 => 1}, B => {B1 => 2, B2 => 1}, C => {C1 => 3, C2 => 1}};

countOutputClasses($node, $count)

Count instances of outputclass attributes

     Parameter  Description
  1  $node      Node
  2  $count     Count so far.

Example:

    my $a = Data::Edit::Xml::newTree("a", id=>1, class=>2, href=>3, outputclass=>4);


    is_deeply { 4 => 1 }, $a->countOutputClasses;                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

countReport($node, @context)

Count tags, attributes, words below the specified node

     Parameter  Description
  1  $node      Node to count from
  2  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>aaa bbb ccc</b>
    <c>AAA BBB CCC</c>
    <c>aaa AAA</c>
  </a>
  END


    my $t = $a->countReport;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $t eq <<END;
     Tag  Count
  1    3  CDATA
  2    1  a
  3    1  b
  4    2  c
  END

cr is a synonym for countReport.

changeReasonCommentSelectionSpecification()

Provide a specification to select change reason comments to be inserted as text into a parse tree. A specification can be either:

the name of a code to be accepted,
a regular expression which matches the codes to be accepted,
a hash whose keys are defined for the codes to be accepted or
undef (the default) to specify that no such comments should be accepted.

Example:

    changeReasonCommentSelectionSpecification = {ccc=>1, ddd=>1};                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    changeReasonCommentSelectionSpecification = undef;                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::changeReasonCommentSelectionSpecification

crc($node, $code, $reason)

Insert a comment consisting of a code and an optional reason as text into the parse tree to indicate the location of changes to the parse tree. As such comments tend to become very numerous, only comments whose codes matches the specification provided in changeReasonCommentSelectionSpecification are accepted for insertion. Subsequently these comments can be easily located using:

grep -nr "<!--code"

on the file containing a printed version of the parse tree. Please note that these comments will be removed if the output file is reparsed.

Returns the specified $node.

     Parameter  Description
  1  $node      Node being changed
  2  $code      Reason code
  3  $reason    Optional text description of change

Example:

   {my $a = Data::Edit::Xml::new("<a><b/></a>");

    my ($b) = $a->contents;

    changeReasonCommentSelectionSpecification = {ccc=>1, ddd=>1};

    $b->putFirst(my $c = $b->newTag(q(c)));


    $c->crc($_) for qw(aaa ccc);                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $a;
  <a>
    <b><!--ccc-->
      <c/>
    </b>
  </a>
  END

    changeReasonCommentSelectionSpecification = undef;

    $c->putFirst(my $d = $c->newTag(q(d)));


    $d->crc($_) for qw(aaa ccc);                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok <<END eq -p $a;
  <a>
    <b><!--ccc-->
      <c>
        <d/>
      </c>
    </b>
  </a>
  END

howFirst($node)

Return the depth to which the specified $node is first else 0.

     Parameter  Description
  1  $node      Node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok $d->howFirst     == 4;                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

howLast($node)

Return the depth to which the specified $node is last else 0.

     Parameter  Description
  1  $node      Node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok $f->howLast      == 3;                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

howOnlyChild($node)

Return the depth to which the specified $node is an only child else 0.

     Parameter  Description
  1  $node      Node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok $d->howOnlyChild == 2;                                                       # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

howFar($first, $second)

Return how far the first node is from the second node along a path through their common ancestor.

     Parameter  Description
  1  $first     First node
  2  $second    Second node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;

    is_deeply [$d->commonAdjacentAncestors($C)], [$b, $B];


    ok $d->howFar($d) == 0;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $d->howFar($a) == 3;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $b->howFar($B) == 1;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $d->howFar($f) == 5;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok $d->howFar($C) == 4;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

howFarAbove($above, $below)

Return how far the first node is above the second node is or 0 if the first node is not strictly above the second node.

     Parameter  Description
  1  $above     First node above
  2  $below     Second node below

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok  $a->howFarAbove($d) == 3;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$d->howFarAbove($c);                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

howFarBelow($below, $above)

Return how far the first node is below the second node is or 0 if the first node is not strictly below the second node.

     Parameter  Description
  1  $below     First node below
  2  $above     Second node above

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
    </b>
    <b>
      <c/>
    </b>
    <e>
      <f/>
    </e>
  </a>
  END

    my ($d, $c, $b, $C, $B, $f, $e) = $a->byList;


    ok  $d->howFarBelow($a) == 3;                                                   # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲



    ok !$c->howFarBelow($d);                                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Required clean up

Insert required clean up tags.

requiredCleanUp($node, $outputclass)

Replace a $node with a required cleanup node with special characters replaced by symbols and with the optional $outputclass.

Returns the specified $node.

     Parameter     Description
  1  $node         Node
  2  $outputclass  Optional outputclass attribute of required cleanup tag

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        ccc
      </c>
    </b>
  </a>
  END

    my ($b) = $a->contents;


    $b->requiredCleanUp(q(33));                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <required-cleanup outputclass="33">&lt;b&gt;
    &lt;c&gt;
        ccc
      &lt;/c&gt;
  &lt;/b&gt;
  </required-cleanup>
  </a>
  END

replaceWithRequiredCleanUp($node, @text)

Replace a $node with required cleanup @text and return the new node

     Parameter  Description
  1  $node      Node to be replace
  2  @text      Clean up message

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
  </a>
  END

    my ($b) = $a->contents;


    $b->replaceWithRequiredCleanUp(q(bb));                                          # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <required-cleanup>bb</required-cleanup>
  </a>
  END

putFirstRequiredCleanUp($node, @text)

Place a required cleanup first under a specified $node using the specified @text and return the required clean up node.

     Parameter  Description
  1  $node      Node
  2  @text      Clean up message

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b/>
  </a>
  END


    $a->putFirstRequiredCleanUp(qq(1111
));                                        # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <b/>
  </a>
  END

putLastRequiredCleanUp($node, @text)

Place a required cleanup last under a specified $node using the specified @text and return the required clean up node.

     Parameter  Description
  1  $node      Node
  2  @text      Clean up message

Example:

    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <b/>
  </a>
  END


    $a->putLastRequiredCleanUp(qq(4444
));                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <b/>
    <required-cleanup>4444
  </required-cleanup>
  </a>
  END

putNextRequiredCleanUp($node, @text)

Place a required cleanup next after a specified $node using the specified @text and return the required clean up node.

     Parameter  Description
  1  $node      Node
  2  @text      Clean up message

Example:

    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <b/>
    <required-cleanup>4444
  </required-cleanup>
  </a>
  END


    $a->go(q(b))->putNextRequiredCleanUp(qq(3333
));                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <b/>
    <required-cleanup>3333
  </required-cleanup>
    <required-cleanup>4444
  </required-cleanup>
  </a>
  END

putPrevRequiredCleanUp($node, $text)

Place a required cleanup before a specified $node using the specified @text and return the required clean up node.

     Parameter  Description
  1  $node      Node
  2  $text      Clean up message

Example:

    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <b/>
    <required-cleanup>3333
  </required-cleanup>
    <required-cleanup>4444
  </required-cleanup>
  </a>
  END


    $a->go(q(b))->putPrevRequiredCleanUp(qq(2222
));                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <required-cleanup>1111
  </required-cleanup>
    <required-cleanup>2222
  </required-cleanup>
    <b/>
    <required-cleanup>3333
  </required-cleanup>
    <required-cleanup>4444
  </required-cleanup>
  </a>
  END

Conversions

Methods useful for conversions from word, HTML and Dita to Dita.

Dita Conversions

Methods useful for enhancing Dita.

ditaGetConRef($ref, $sourceFile, $matchContext, $matchContextOnly)

Get the value of a conref attribute given a valid Dita $reference found in the file named $sourceFile. Optionally, if the regular expression $matchContext is supplied then nodes whose context (single blank separated) tags match this regular expression will be considered first as a target of the conref, if such a search fails then any unique node with the matching id will be the considered next as a possible target unless the optional $matchContextOnly parameter is true. Note: all the conrefs in the included content will also be expanded creating the possibility of endless circular expansions.

     Parameter          Description
  1  $ref               Dita ref value of conref
  2  $sourceFile        Source file containing conref
  3  $matchContext      Optional regular expression of acceptable context
  4  $matchContextOnly  Confine search to acceptable context.

Example:

    my $dir = temporaryFolder;
    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b">
      <c/>
    </b>
  </a>
  END

    my $target = fpe($dir, qw(target xml));
    owf($target, -p $a);


    my $b = ditaGetConRef("target.xml#a/b", $dir);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $b eq <<END;
  <b id="b">
    <c/>
  </b>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <b id="B" conref="target.xml#a/b"/>
  </a>
  END
    my $target2 = fpe($dir, qw(target2 xml));
    owf($target2, -p $A);

    my $B = Data::Edit::Xml::new(<<END);
  <a>
    <b id="C" conref="target2.xml#a/B"/>
  </a>
  END

    $B->ditaExpandAllConRefs($dir);
    ok -p $B eq <<END;
  <a>
    <b id="C">
      <c/>
    </b>
  </a>
  END

    my $CF = owf(fpe($dir, qw(source xml)), <<END);
  <a>
    <b id="D" conref="target2.xml#a/B"/>
  </a>
  END

    my $C = Data::Edit::Xml::new($CF);

    $C->first__ditaReplaceAnyConref;
    ok -p $C eq <<END;
  <a>
    <b id="D">
      <c/>
    </b>
  </a>
  END

    my $DF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="E" conref="target2.xml#a/B"/>
  END

    my $D = Data::Edit::Xml::new($DF);

    $D->ditaReplaceAnyConref;
    ok -p $D eq <<END;
  <b id="E">
    <c/>
  </b>
  END

    my $EF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="F" conref="target2.xml"/>
  END

    my $E = Data::Edit::Xml::new($EF);

    $E->ditaReplaceAnyConref;

    ok -p $E eq <<END;
  <a id="F">
    <b id="B">
      <c/>
    </b>
  </a>
  END

    clearFolder($dir, 3);

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::ditaGetConRef

ditaReplaceConref($node, $sourceFile)

Replace a conref on the specified $node in the specified source file $sourceFile with the parse tree of the referenced content. Returns the referenced content. Confesses if there is no conref to replace on $node.

     Parameter    Description
  1  $node        Node with conref attribute
  2  $sourceFile  Source file containing the node.

Example:

    my $dir = temporaryFolder;
    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b">
      <c/>
    </b>
  </a>
  END

    my $target = fpe($dir, qw(target xml));
    owf($target, -p $a);

    my $b = ditaGetConRef("target.xml#a/b", $dir);
    ok -p $b eq <<END;
  <b id="b">
    <c/>
  </b>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <b id="B" conref="target.xml#a/b"/>
  </a>
  END
    my $target2 = fpe($dir, qw(target2 xml));
    owf($target2, -p $A);

    my $B = Data::Edit::Xml::new(<<END);
  <a>
    <b id="C" conref="target2.xml#a/B"/>
  </a>
  END

    $B->ditaExpandAllConRefs($dir);
    ok -p $B eq <<END;
  <a>
    <b id="C">
      <c/>
    </b>
  </a>
  END

    my $CF = owf(fpe($dir, qw(source xml)), <<END);
  <a>
    <b id="D" conref="target2.xml#a/B"/>
  </a>
  END

    my $C = Data::Edit::Xml::new($CF);

    $C->first__ditaReplaceAnyConref;
    ok -p $C eq <<END;
  <a>
    <b id="D">
      <c/>
    </b>
  </a>
  END

    my $DF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="E" conref="target2.xml#a/B"/>
  END

    my $D = Data::Edit::Xml::new($DF);

    $D->ditaReplaceAnyConref;
    ok -p $D eq <<END;
  <b id="E">
    <c/>
  </b>
  END

    my $EF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="F" conref="target2.xml"/>
  END

    my $E = Data::Edit::Xml::new($EF);

    $E->ditaReplaceAnyConref;

    ok -p $E eq <<END;
  <a id="F">
    <b id="B">
      <c/>
    </b>
  </a>
  END

    clearFolder($dir, 3);

ditaReplaceAnyConref($node, @context)

Replace a conref with the referenced content if we are in the optional context and the target of the conref can be located. Returns true regardless of any processing performed to allow Dita::Pcd processing to continue.

     Parameter  Description
  1  $node      Node with conref attribute
  2  @context   Optional context.

Example:

    my $dir = temporaryFolder;
    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b">
      <c/>
    </b>
  </a>
  END

    my $target = fpe($dir, qw(target xml));
    owf($target, -p $a);

    my $b = ditaGetConRef("target.xml#a/b", $dir);
    ok -p $b eq <<END;
  <b id="b">
    <c/>
  </b>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <b id="B" conref="target.xml#a/b"/>
  </a>
  END
    my $target2 = fpe($dir, qw(target2 xml));
    owf($target2, -p $A);

    my $B = Data::Edit::Xml::new(<<END);
  <a>
    <b id="C" conref="target2.xml#a/B"/>
  </a>
  END

    $B->ditaExpandAllConRefs($dir);
    ok -p $B eq <<END;
  <a>
    <b id="C">
      <c/>
    </b>
  </a>
  END

    my $CF = owf(fpe($dir, qw(source xml)), <<END);
  <a>
    <b id="D" conref="target2.xml#a/B"/>
  </a>
  END

    my $C = Data::Edit::Xml::new($CF);

    $C->first__ditaReplaceAnyConref;
    ok -p $C eq <<END;
  <a>
    <b id="D">
      <c/>
    </b>
  </a>
  END

    my $DF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="E" conref="target2.xml#a/B"/>
  END

    my $D = Data::Edit::Xml::new($DF);


    $D->ditaReplaceAnyConref;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $D eq <<END;
  <b id="E">
    <c/>
  </b>
  END

    my $EF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="F" conref="target2.xml"/>
  END

    my $E = Data::Edit::Xml::new($EF);


    $E->ditaReplaceAnyConref;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $E eq <<END;
  <a id="F">
    <b id="B">
      <c/>
    </b>
  </a>
  END

    clearFolder($dir, 3);

ditaReplaceAnyConrefIdeallyWithMatchingTag($node, @context)

Replace a conref with the referenced content if we are in the optional context and the target of the conref can be located. If multiple possible targets exists, priority will be given to any that match the tag of $node. Returns the root of the parse tree containing the new content or undef if no new content was located.

     Parameter  Description
  1  $node      Node with conref attribute
  2  @context   Optional context.

Example:

    my $dir = temporaryFolder;
    my $target = Data::Edit::Xml::new(<<END);
  <a>
    <c id="b"/>
    <b id="b"/>
  </a>
  END

    owf(fpe($dir, qw(target xml)), -p $target);

    my $s = Data::Edit::Xml::new(q(<a conref="target.xml#a/b"/>));
    $s->inputFile = fpe($dir, qw(source xml));

    my $s1 = $s->clone->change_c;

       $s1->ditaReplaceAnyConrefIdeallyWithMatchingTag;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $s1 eq <<END;
  <c id="b"/>
  END

    my  $s2 = $s->clone->change_b;
    ok !$s2->ditaReplaceAnyConrefInContext(qr(\Ac A\Z));
        $s2->ditaReplaceAnyConrefInContext(qr(\Ac a\Z));
    ok -p $s2 eq <<END;
  <c id="b"/>
  END

    my $b = ditaGetConRef("target.xml#a/b", $dir, qr(\Ab\Z));
    ok -p $b eq <<END;
  <b id="b"/>
  END

    my $c = ditaGetConRef("target.xml#a/b", $dir, qr(\Ac a\Z));
    ok -p $c eq <<END;
  <c id="b"/>
  END

    my $d = ditaGetConRef("target.xml#a/b", $dir, qr(\Ad\Z));
    ok -p $c eq <<END;
  <c id="b"/>
  END

    ok !ditaGetConRef("target.xml#a/b", $dir, qr(\A(d|e)\Z), 1);

    clearFolder($dir, 3);

ditaReplaceAnyConrefInContext($node, $context, @context)

Replace a conref with the referenced content if we are in the optional context and the target of the conref can be located and the context of the target node matches the regular expression $context. Returns the root of the parse tree containing the new content or undef if no new content was located.

     Parameter  Description
  1  $node      Node with conref attribute
  2  $context   Tags to match
  3  @context   Optional context.

Example:

    my $dir = temporaryFolder;
    my $target = Data::Edit::Xml::new(<<END);
  <a>
    <c id="b"/>
    <b id="b"/>
  </a>
  END

    owf(fpe($dir, qw(target xml)), -p $target);

    my $s = Data::Edit::Xml::new(q(<a conref="target.xml#a/b"/>));
    $s->inputFile = fpe($dir, qw(source xml));

    my $s1 = $s->clone->change_c;
       $s1->ditaReplaceAnyConrefIdeallyWithMatchingTag;
    ok -p $s1 eq <<END;
  <c id="b"/>
  END

    my  $s2 = $s->clone->change_b;

    ok !$s2->ditaReplaceAnyConrefInContext(qr(\Ac A\Z));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


        $s2->ditaReplaceAnyConrefInContext(qr(\Ac a\Z));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $s2 eq <<END;
  <c id="b"/>
  END

    my $b = ditaGetConRef("target.xml#a/b", $dir, qr(\Ab\Z));
    ok -p $b eq <<END;
  <b id="b"/>
  END

    my $c = ditaGetConRef("target.xml#a/b", $dir, qr(\Ac a\Z));
    ok -p $c eq <<END;
  <c id="b"/>
  END

    my $d = ditaGetConRef("target.xml#a/b", $dir, qr(\Ad\Z));
    ok -p $c eq <<END;
  <c id="b"/>
  END

    ok !ditaGetConRef("target.xml#a/b", $dir, qr(\A(d|e)\Z), 1);

    clearFolder($dir, 3);

ditaExpandAllConRefs($tree, $sourceFile)

Expand all the conrefs in the specified $parseTree relative to the specified $sourceFile.

     Parameter    Description
  1  $tree        Parse tree
  2  $sourceFile  Source file we are expanding in

Example:

    my $dir = temporaryFolder;
    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="b">
      <c/>
    </b>
  </a>
  END

    my $target = fpe($dir, qw(target xml));
    owf($target, -p $a);

    my $b = ditaGetConRef("target.xml#a/b", $dir);
    ok -p $b eq <<END;
  <b id="b">
    <c/>
  </b>
  END

    my $A = Data::Edit::Xml::new(<<END);
  <a>
    <b id="B" conref="target.xml#a/b"/>
  </a>
  END
    my $target2 = fpe($dir, qw(target2 xml));
    owf($target2, -p $A);

    my $B = Data::Edit::Xml::new(<<END);
  <a>
    <b id="C" conref="target2.xml#a/B"/>
  </a>
  END


    $B->ditaExpandAllConRefs($dir);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $B eq <<END;
  <a>
    <b id="C">
      <c/>
    </b>
  </a>
  END

    my $CF = owf(fpe($dir, qw(source xml)), <<END);
  <a>
    <b id="D" conref="target2.xml#a/B"/>
  </a>
  END

    my $C = Data::Edit::Xml::new($CF);

    $C->first__ditaReplaceAnyConref;
    ok -p $C eq <<END;
  <a>
    <b id="D">
      <c/>
    </b>
  </a>
  END

    my $DF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="E" conref="target2.xml#a/B"/>
  END

    my $D = Data::Edit::Xml::new($DF);

    $D->ditaReplaceAnyConref;
    ok -p $D eq <<END;
  <b id="E">
    <c/>
  </b>
  END

    my $EF = owf(fpe($dir, qw(source xml)), <<END);
  <a id="F" conref="target2.xml"/>
  END

    my $E = Data::Edit::Xml::new($EF);

    $E->ditaReplaceAnyConref;

    ok -p $E eq <<END;
  <a id="F">
    <b id="B">
      <c/>
    </b>
  </a>
  END

    clearFolder($dir, 3);

ditaAbsoluteHref($node, $sourceFile)

Return the absolute value of the href of a specified $node relative to the specified $sourceFile or undef if the node has no href attribute.

     Parameter    Description
  1  $node        Node containing href
  2  $sourceFile  Source file

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a href="bbb.txt">
  </a>
  END


    ok $a->ditaAbsoluteHref(q(/home/aaa/)) eq q(/home/aaa/bbb.txt);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

ditaListToChoices($list, @context)

Change the specified $list to choices.

     Parameter  Description
  1  $list      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <ol>
    <li>
      <p/>
    </li>
    <li>
      <p/>
    </li>
  </ol>
  END


    $a->ditaListToChoices;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <choices>
    <choice>
      <p/>
    </choice>
    <choice>
      <p/>
    </choice>
  </choices>
  END

ditaListToSteps($list, @context)

Change the specified $node to steps and its contents to cmd\step optionally only in the specified context.

     Parameter  Description
  1  $list      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <dita>
    <ol>
      <li>
        <p>aaa</p>
      </li>
      <li>
        <p>bbb</p>
      </li>
    </ol>
  </dita>
  END


    $a->first->ditaListToSteps;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <dita>
    <steps>
      <step>
        <cmd>aaa</cmd>
      </step>
      <step>
        <cmd>bbb</cmd>
      </step>
    </steps>
  </dita>
  END

ditaListToStepsUnordered($list, @context)

Change the specified $node to steps-unordered and its contents to cmd\step optionally only in the specified context.

     Parameter  Description
  1  $list      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <dita>
    <ol>
      <li>aaa</li>
      <li>bbb</li>
    </ol>
  </dita>
  END


    $a->first->ditaListToStepsUnordered;                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <dita>
    <steps-unordered>
      <step>
        <cmd>aaa</cmd>
      </step>
      <step>
        <cmd>bbb</cmd>
      </step>
    </steps-unordered>
  </dita>
  END

ditaListToSubSteps($list, @context)

Change the specified $node to substeps and its contents to cmd\step optionally only in the specified context.

     Parameter  Description
  1  $list      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <dita>
    <ol>
      <li>aaa</li>
      <li>bbb</li>
    </ol>
  </dita>
  END


    $a->first->ditaListToSubSteps;                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <dita>
    <substeps>
      <substep>
        <cmd>aaa</cmd>
      </substep>
      <substep>
        <cmd>bbb</cmd>
      </substep>
    </substeps>
  </dita>
  END

ditaStepsToList($steps, $tag, @context)

Change the specified $node to a node with name $tag or to ol if $tag is not supplied and its cmd\step content to li to create a list optionally only in the specified context.

     Parameter  Description
  1  $steps     Node
  2  $tag       New tag if not ol
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    ok -p $a eq <<END;
  <dita>
    <ol>
      <li>
        <p>aaa</p>
      </li>
      <li>
        <p>bbb</p>
      </li>
    </ol>
  </dita>
  END


    $a->first->ditaStepsToList;                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <dita>
    <ol>
      <li>aaa</li>
      <li>bbb</li>
    </ol>
  </dita>
  END

ditaStepsToChoices($steps, @context)

Change the specified $node to choices.

     Parameter  Description
  1  $steps     Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <steps>
    <step>
      <cmd>Command</cmd>
      <stepresult>
  Step result
  </stepresult>
      <stepxmp>
  Step example
  </stepxmp>
    </step>
    <step>
      <cmd>Command</cmd>
      <stepresult>
  Step result
  </stepresult>
      <stepxmp>
  Step example
  </stepxmp>
    </step>
  </steps>
  END


    $a->ditaStepsToChoices;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <choices>
    <choice>
      <p>Command</p>
  Step result
  Step example
    </choice>
    <choice>
      <p>Command</p>
  Step result
  Step example
    </choice>
  </choices>
  END

ditaConvertSubStepsToSteps($substeps, @context)

Change the $substeps to steps and return the steps on success or undef on failure.

     Parameter  Description
  1  $substeps  Substeps
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <substeps>
    <substep>
      <cmd>C1</cmd>
    </substep>
    <substep>
      <cmd>C2</cmd>
    </substep>
  </substeps>
  END


    $a->ditaConvertSubStepsToSteps;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <steps>
    <step>
      <cmd>C1</cmd>
    </step>
    <step>
      <cmd>C2</cmd>
    </step>
  </steps>
  END

ditaListToTable($node, @context)

Convert a list to a table in situ - as designed by MiM.

     Parameter  Description
  1  $node      List node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <ul id="Table3" outputclass="fcRowList">
      <li>
          <p id="1">1111</p>
          <p id="2">2222</p>
          <p id="3">3333</p>
          <p id="4">4444</p>
      </li>
      <li>
          <p id="tableToListA1" outputclass="1">aaaa1111</p>
          <p id="tableToListA2" outputclass="1">aaaa2222</p>
          <p id="tableToListA3" outputclass="1">aaaa3333</p>
          <p id="tableToListA4" outputclass="1">aaaa4444</p>
      </li>
      <li>
          <p id="tableToListB1" outputclass="1">bbbb1111</p>
          <p id="tableToListB2" outputclass="1">bbbb2222</p>
          <p id="tableToListB3" outputclass="1">bbbb3333</p>
      </li>
      <li>
          <p id="tableToListC1" outputclass="1">cccc1111</p>
          <p id="tableToListC2" outputclass="1">cccc2222</p>
          <p id="tableToListC3" outputclass="1">cccc3333</p>
          <p id="tableToListC4" outputclass="1">cccc4444</p>
          <p id="tableToListC5" outputclass="1">cccc5555</p>
      </li>
  </ul>
  END

    $a->ditaListToTable;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok nws(-p $a) eq nws(<<END)
  <table id="Table3" outputclass="fcRowList">
    <tgroup cols="5">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <colspec colname="c3" colnum="3" colwidth="1*"/>
      <colspec colname="c4" colnum="4" colwidth="1*"/>
      <colspec colname="c5" colnum="5" colwidth="1*"/>
      <thead>
        <row>
          <entry/>
          <entry/>
          <entry/>
          <entry/>
          <entry/>
        </row>
      </thead>
      <tbody>
        <row>
          <entry id="1">1111</entry>
          <entry id="2">2222</entry>
          <entry id="3">3333</entry>
          <entry id="4">4444</entry>
        </row>
        <row>
          <entry id="tableToListA1" outputclass="1">aaaa1111</entry>
          <entry id="tableToListA2" outputclass="1">aaaa2222</entry>
          <entry id="tableToListA3" outputclass="1">aaaa3333</entry>
          <entry id="tableToListA4" outputclass="1">aaaa4444</entry>
        </row>
        <row>
          <entry id="tableToListB1" outputclass="1">bbbb1111</entry>
          <entry id="tableToListB2" outputclass="1">bbbb2222</entry>
          <entry id="tableToListB3" outputclass="1">bbbb3333</entry>
        </row>
        <row>
          <entry id="tableToListC1" outputclass="1">cccc1111</entry>
          <entry id="tableToListC2" outputclass="1">cccc2222</entry>
          <entry id="tableToListC3" outputclass="1">cccc3333</entry>
          <entry id="tableToListC4" outputclass="1">cccc4444</entry>
          <entry id="tableToListC5" outputclass="1">cccc5555</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END
   }

ditaMergeLists($node, @context)

Merge the specified $node with the preceding or following list or steps or substeps if possible and return the specified $node regardless.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <li id="1"/>
    <ol/>
    <ol>
      <li id="2"/>
      <li id="3"/>
    </ol>
  </a>
  END


    $a x= sub{$_->ditaMergeLists};                                                  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <ol>
      <li id="1"/>
      <li id="2"/>
      <li id="3"/>
    </ol>
  </a>
  END

mergeLikeElements($node, @context)

Merge two of the same elements into one, retaining the order of any children. Return the original $node if the request succeeds, else return undef.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <x><a>aa</a><b>bb</b><b>cc</b><b>dd</b><b>ee</b></x>
  END

    ok -p $a eq <<END;
  <x>
    <a>aa</a>
    <b>bb</b>
    <b>cc</b>
    <b>dd</b>
    <b>ee</b>
  </x>
  END


    $a->by(sub{$_->mergeLikeElements});  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <x>
    <a>aa</a>
    <b>bb cc dd ee</b>
  </x>
  END

mergeLikeNext($node, @context)

Merge a $node in an optional context with the next node if the two have the same tag by placing the next node first in the current $node and unwrapping the next node. Return undef if the request fails else the current $node. Identical to mergeLikeElements

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb</b>
    <b>dd</b>
  </a>
  END


    $a->first->mergeLikeNext;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>bb dd</b>
  </a>
  END

mln is a synonym for mergeLikeNext.

mergeLikePrev($node, @context)

Merge a $node in an optional context with the previous node if the two have the same tag by placing the previous node first in the current $node and unwrapping the previous node. Return undef if the request fails else return the specified $node.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>bb</b>
    <b>dd</b>
  </a>
  END


    $a->last->mergeLikePrev;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <b>bb dd</b>
  </a>
  END

mlp is a synonym for mergeLikePrev.

mergeOnlyChildLikeNext($node, @context)

Merge a $node if it is the only child of its parent with a preceding node of the same name that is also the only child of its parent and return the specified $node or undef if the request fails.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="1">
       <c/>
    </b>
    <b id="2">
       <c/>
    </b>
  </a>
  END

    $a->go_b_c__mergeOnlyChildLikeNext;
    ok -p $a eq <<END;
  <a>
    <b id="1">
      <c/>
    </b>
  </a>
  END

mocln is a synonym for mergeOnlyChildLikeNext.

mergeOnlyChildLikePrev($node, @context)

Merge a $node if it is the only child of its parent with a preceding node of the same name that is also the only child of its parent and return the specified $node or undef if the request fails.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b id="1">
       <c/>
    </b>
    <b id="2">
       <c/>
    </b>
  </a>
  END

    $a->go_b_1_c__mergeOnlyChildLikePrev;
    ok -p $a eq <<END;
  <a>
    <b id="2">
      <c/>
    </b>
  </a>
  END

moclp is a synonym for mergeOnlyChildLikePrev.

mergeOnlyChildLikePrevLast($node, @context)

Merge a $node if it is the only child of its parent with a preceding node with the same tag that is the last child of its parent and return the previous $node or undef if the request fails.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b><c/><d>1</d></b>
    <b>    <d>2</d></b>
  </a>
  END

    my $c = $a->last__last__mergeOnlyChildLikePrevLast;
    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
      <d>1 2</d>
    </b>
  </a>
  END

    ok -p $c eq <<END
  <d>1 2</d>
  END

ditaMaximumNumberOfEntriesInATGroupRow($tgroup)

Return the maximum number of entries in the rows of the specified $table or undef if not a table.

     Parameter  Description
  1  $tgroup    TGroup node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
          <entry/>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    my $g = $a->go_tgroup;


    ok $g->ditaMaximumNumberOfEntriesInATGroupRow == 3;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 1,
    colSpec => 1,
    maxBody => 3,
    maxBodyMinusPadding => 3,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 1,
    minHead => 1,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

    $g->ditaRemoveTGroupTrailingEmptyEntries;

    ok -p $a eq <<END;
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

ditaTGroupStatistics($tgroup)

Return statistics about the rows in a given table

     Parameter  Description
  1  $tgroup    Table group node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
          <entry/>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    my $g = $a->go_tgroup;

    ok $g->ditaMaximumNumberOfEntriesInATGroupRow == 3;


    is_deeply $g->ditaTGroupStatistics,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  bless({
    colsAttribute => 1,
    colSpec => 1,
    maxBody => 3,
    maxBodyMinusPadding => 3,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 1,
    minHead => 1,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

    $g->ditaRemoveTGroupTrailingEmptyEntries;

    ok -p $a eq <<END;
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

ditaAddColSpecToTGroup($tgroup, $number)

Add the specified $number of column specification to a specified $tgroup which does not have any already.

     Parameter  Description
  1  $tgroup    Tgroup node
  2  $number    Number of colspecs to add

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup>
      <tbody>
        <row><entry/></row>
        <row><entry/><entry/></row>
        <row><entry/><entry/><entry/></row>
        <row><entry/><entry/></row>
        <row/>
      </tbody>
    </tgroup>
  </table>
  END

    ok 3 == $a->go_tgroup->ditaMaximumNumberOfEntriesInATGroupRow;

    $a->first->ditaAddColSpecToTGroup(3);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END
  <table>
    <tgroup cols="3">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <colspec colname="c3" colnum="3" colwidth="1*"/>
      <tbody>
        <row>
          <entry/>
        </row>
        <row>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry/>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry/>
          <entry/>
        </row>
        <row/>
      </tbody>
    </tgroup>
  </table>
  END
   }

ditaFixTGroupColSpec($tgroup)

Fix the colspec attribute and colspec nodes of the specified $tgroup.

     Parameter  Description
  1  $tgroup    Tgroup node

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup>
      <tbody>
        <row><entry/></row>
        <row><entry/><entry/></row>
        <row><entry/><entry/><entry/></row>
        <row><entry/><entry/></row>
        <row>
          <entry>
            <table>
              <tbody>
                <row><entry/><entry/><entry/><entry/><entry/><entry/><entry/></row>
              </tbody>
            </table>
          </entry>
        </row>
     </tbody>
   </tgroup>
  </table>
  END


    $a->go_tgroup->ditaFixTGroupColSpec;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END
  <table>
    <tgroup cols="3">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <colspec colname="c3" colnum="3" colwidth="1*"/>
      <tbody>
        <row>
          <entry/>
        </row>
        <row>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry/>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry>
            <table>
              <tbody>
                <row>
                  <entry/>
                  <entry/>
                  <entry/>
                  <entry/>
                  <entry/>
                  <entry/>
                  <entry/>
                </row>
              </tbody>
            </table>
          </entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END
   }

ditaRemoveTGroupTrailingEmptyEntries($tgroup)

Remove empty trailing entry

     Parameter  Description
  1  $tgroup    Table node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
          <entry/>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
          <entry/>
          <entry/>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    my $g = $a->go_tgroup;

    ok $g->ditaMaximumNumberOfEntriesInATGroupRow == 3;

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 1,
    colSpec => 1,
    maxBody => 3,
    maxBodyMinusPadding => 3,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 1,
    minHead => 1,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");


    $g->ditaRemoveTGroupTrailingEmptyEntries;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

fixTGroup($tgroup)

Fix the specified $tgroup so that each row has the same number of entries with this number reflected in the tgroup.cols= attribute and colspec nodes.

     Parameter  Description
  1  $tgroup    TGroup node

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    my $g = $a->go_tgroup;

    $g->ditaAddPadEntriesToTGroupRows(2);

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 1,
    colSpec => 1,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");


    $g->fixTGroup;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <table>
    <tgroup cols="2">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <thead>
        <row>
          <entry>aaaa</entry>
          <entry/>
        </row>
        <row>
          <entry>bbbb</entry>
          <entry/>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
          <entry/>
        </row>
        <row>
          <entry>dddd</entry>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 2,
    colSpec => 2,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,

  }, "Data::Edit::Xml::Table::Statistics");

    $a->fixTable;
    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 2,
    colSpec => 2,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

fixTable($table)

Fix the specified $table so that each row has the same number of entries with this number reflected in the tgroup.cols= attribute and colspec nodes.

     Parameter  Description
  1  $table     Table node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    my $g = $a->go_tgroup;

    $g->ditaAddPadEntriesToTGroupRows(2);

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 1,
    colSpec => 1,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

    $g->fixTGroup;

    ok -p $a eq <<END;
  <table>
    <tgroup cols="2">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <thead>
        <row>
          <entry>aaaa</entry>
          <entry/>
        </row>
        <row>
          <entry>bbbb</entry>
          <entry/>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
          <entry/>
        </row>
        <row>
          <entry>dddd</entry>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 2,
    colSpec => 2,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,

  }, "Data::Edit::Xml::Table::Statistics");


    $a->fixTable;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 2,
    colSpec => 2,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

fixEntryColSpan($entry)

Fix the colspan on an entry assumed to be under row, tbody, tgroup with @cols and colspecs' set

     Parameter  Description
  1  $entry     Entry

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="7">
      <colspec colname="a"/>
      <colspec colname="b"/>
      <colspec colname="c"/>
      <colspec colname="d"/>
      <colspec colname="e"/>
      <colspec colname="f"/>
      <colspec colname="g"/>
      <tbody>
        <row>
          <entry colspan="7"/>
        </row>
        <row>
          <entry colspan="2"/>
          <entry colspan="3"/>
          <entry colspan="2"/>
        </row>
        <row>
          <entry/>
          <entry rowspan="2"/>
          <entry colspan="2"/>
          <entry colspan="2"/>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    $a->by(sub
     {my ($e) = @_;
      if ($e->at_entry)

       {$e->fixEntryColSpan;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

        $e->fixEntryRowSpan;
       }
     });

    ok -p $a eq <<END;
  <table>
    <tgroup cols="7">
      <colspec colname="a"/>
      <colspec colname="b"/>
      <colspec colname="c"/>
      <colspec colname="d"/>
      <colspec colname="e"/>
      <colspec colname="f"/>
      <colspec colname="g"/>
      <tbody>
        <row>
          <entry nameend="g" namest="a"/>
        </row>
        <row>
          <entry nameend="b" namest="a"/>
          <entry nameend="e" namest="c"/>
          <entry nameend="g" namest="f"/>
        </row>
        <row>
          <entry/>
          <entry morerows="1"/>
          <entry nameend="d" namest="c"/>
          <entry nameend="f" namest="e"/>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

fixEntryRowSpan($entry)

Fix the rowspan on an entry

     Parameter  Description
  1  $entry     Entry

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="7">
      <colspec colname="a"/>
      <colspec colname="b"/>
      <colspec colname="c"/>
      <colspec colname="d"/>
      <colspec colname="e"/>
      <colspec colname="f"/>
      <colspec colname="g"/>
      <tbody>
        <row>
          <entry colspan="7"/>
        </row>
        <row>
          <entry colspan="2"/>
          <entry colspan="3"/>
          <entry colspan="2"/>
        </row>
        <row>
          <entry/>
          <entry rowspan="2"/>
          <entry colspan="2"/>
          <entry colspan="2"/>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    $a->by(sub
     {my ($e) = @_;
      if ($e->at_entry)
       {$e->fixEntryColSpan;

        $e->fixEntryRowSpan;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

       }
     });

    ok -p $a eq <<END;
  <table>
    <tgroup cols="7">
      <colspec colname="a"/>
      <colspec colname="b"/>
      <colspec colname="c"/>
      <colspec colname="d"/>
      <colspec colname="e"/>
      <colspec colname="f"/>
      <colspec colname="g"/>
      <tbody>
        <row>
          <entry nameend="g" namest="a"/>
        </row>
        <row>
          <entry nameend="b" namest="a"/>
          <entry nameend="e" namest="c"/>
          <entry nameend="g" namest="f"/>
        </row>
        <row>
          <entry/>
          <entry morerows="1"/>
          <entry nameend="d" namest="c"/>
          <entry nameend="f" namest="e"/>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

ditaConvertDlToUl($dl)

Convert a Dita $dl to a ul if each dlentry has only dt or dl elements but not both. Return undef if such a conversion is not possible else return the new ul node.

     Parameter  Description
  1  $dl        Dl

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <dl>
    <dlentry><dt>A</dt><dt>B</dt><dt>C</dt></dlentry>
    <dlentry><dd>a</dd><dd>b</dd><dd>b</dd></dlentry>
  </dl>
  END


    $a->ditaConvertDlToUl;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>a</li>
    <li>b</li>
    <li>b</li>
  </ul>
  END

    my $b = Data::Edit::Xml::new(<<END);
  <dl>
    <dlentry><dt>A</dt><dd>a</dd></dlentry>
  </dl>
  END


    ok !$a->ditaConvertDlToUl;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

ditaConvertOlToSubSteps($ol, @context)

Convert a Dita $ul to substeps else undef if this is not possible.

     Parameter  Description
  1  $ol        Ul
  2  @context   Context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <ol>
    <li>A</li>
    <li>B</li>
    <li>C</li>
  </ol>
  END


    $a->ditaConvertOlToSubSteps;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <substeps>
    <substep>
      <cmd>A</cmd>
    </substep>
    <substep>
      <cmd>B</cmd>
    </substep>
    <substep>
      <cmd>C</cmd>
    </substep>
  </substeps>
  END

ditaConvertUlToSubSteps($ul, @context)

Convert a Dita $ol to substeps else undef if this is not possible.

     Parameter  Description
  1  $ul        Ul
  2  @context   Context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
  </ul>
  END


    $a->ditaConvertUlToSubSteps;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <substeps>
    <substep>
      <cmd>A</cmd>
    </substep>
    <substep>
      <cmd>B</cmd>
    </substep>
    <substep>
      <cmd>C</cmd>
    </substep>
  </substeps>
  END

ditaConvertFromHtmlDl($dl)

Convert a Html $dl to a Dita dl or return undef if this is not possible.

     Parameter  Description
  1  $dl        Dl

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <dl>
    <dt>t11</dt>
    <dd>d11</dd>
    <dd>d12</dd>
    <dt>t21</dt>
    <dd>d21</dd>
    <dd>d22</dd>
    <dt>t31</dt>
    <dd>d31</dd>
    <dd>d32</dd>
  </dl>
  END


    $a->ditaConvertFromHtmlDl;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <dl>
    <dlentry>
      <dt>t11</dt>
      <dd>d11</dd>
      <dd>d12</dd>
    </dlentry>
    <dlentry>
      <dt>t21</dt>
      <dd>d21</dd>
      <dd>d22</dd>
    </dlentry>
    <dlentry>
      <dt>t31</dt>
      <dd>d31</dd>
      <dd>d32</dd>
    </dlentry>
  </dl>
  END

ditaConvertSimpleTableToTable($simpleTable)

Convert a Dita simpletable to a table.

     Parameter     Description
  1  $simpleTable  Simple table

Example:

    my $a = Data::Edit::Xml::new(<<END);
      <simpletable>
        <sthead>
          <stentry>Symbol</stentry>
          <stentry>Meaning</stentry>
        </sthead>
        <strow>
          <stentry>aaaa</stentry>
          <stentry>bbbb</stentry>
        </strow>
      </simpletable>
  END


    $a->ditaConvertSimpleTableToTable;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <table>
    <tgroup cols="2">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <thead>
        <row>
          <entry>Symbol</entry>
          <entry>Meaning</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>aaaa</entry>
          <entry>bbbb</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

ditaCouldConvertConceptToTask($concept)

Check whether a concept could be converted to a task

     Parameter  Description
  1  $concept   Concept to check

Example:

    my $c = Data::Edit::Xml::new(<<END);
  <concept id="c1">
    <title>Title Text</title>
    <conbody>
      <p>Concept 11</p>
      <section>
        <p>A section 11</p>
      </section>
      <section>
        <p>A section 22</p>
      </section>
      <p>Concept 222</p>
    </conbody>
  </concept>
  END

    my $r = $c->ditaConvertConceptToReference;

    ok -p $c eq <<END;
  <reference id="c1">
    <title>Title Text</title>
    <refbody>
      <section>
        <p>Concept 11</p>
      </section>
      <section>
        <p>A section 11</p>
      </section>
      <section>
        <p>A section 22</p>
      </section>
      <section>
        <p>Concept 222</p>
      </section>
    </refbody>
  </reference>
  END

    my $C = $c->ditaConvertReferenceToConcept;
    ok -p $C eq <<END;
  <concept id="c1">
    <title>Title Text</title>
    <conbody>
      <p>Concept 11</p>
      <p>A section 11</p>
      <p>A section 22</p>
      <p>Concept 222</p>
    </conbody>
  </concept>
  END


    ok !$C->ditaCouldConvertConceptToTask;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $ref = Data::Edit::Xml::new(<<END);
  <reference id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
      <title>Testing the S3 Feature for PM 4 1</title>
      <refbody>
          <section>
              <p>To test the S# feature:</p>
              <ol>
                  <li>
                      <p>Set the PCIe link state to L1.2.</p>
                  </li>
                  <li>
                      <p>Issue the command: PM 4 1 command.</p>
                  </li>
              </ol>
          </section>
      </refbody>
  </reference>
  END

    my $concept = $ref->ditaConvertReferenceToConcept;

    ok -p $concept eq <<END;
  <concept id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <conbody>
      <p>To test the S# feature:</p>
      <ol>
        <li>
          <p>Set the PCIe link state to L1.2.</p>
        </li>
        <li>
          <p>Issue the command: PM 4 1 command.</p>
        </li>
      </ol>
    </conbody>
  </concept>
  END


    ok $concept->ditaCouldConvertConceptToTask;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $task = $concept->ditaConvertConceptToTask;

    ok -p $task eq <<END
  <task id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <taskbody>
      <context>
        <p>To test the S# feature:</p>
      </context>
      <steps>
        <step>
          <cmd>Set the PCIe link state to L1.2.</cmd>
        </step>
        <step>
          <cmd>Issue the command: PM 4 1 command.</cmd>
        </step>
      </steps>
      <result/>
    </taskbody>
  </task>
  END

ditaConvertConceptToTask($node, @context)

Convert a Dita concept to a task by representing ol as steps. Return undef if the conversion is not possible because there are no ol else return the specified $concept as as task.

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <concept id="x1">
    <title/>
    <conbody>
      <p>context</p>
      <ol>
        <li> <note>note</note><image/><fig/> <p>cmd</p>  <p>info</p>  </li>
        <li>cmd text<p>info</p>  </li>
      </ol>
      <p>between</p>
      <ol>
        <li>
          <p>cmd <note>first in info</note><note>second in info</note></p>
          <p>info</p>
        </li>
        <li> cmd text <p>info</p> </li>
        <li>
          <ol> <li>substep 1</li> <li>substep 2</li> </ol>
        </li>
      </ol>
      <p>results</p>
    </conbody>
  </concept>
  END


   $a->ditaConvertConceptToTask;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok nws(-p $a) eq nws(<<END);
  <task id="x1">
    <title/>
    <taskbody>
      <context>
        <p>context</p>
      </context>
      <steps>
        <step>
          <note>note</note>
          <note>
            <image/>
          </note>
          <note>
            <fig/>
          </note>
          <cmd>cmd</cmd>
          <info>
            <p>info</p>
          </info>
        </step>
        <step>
          <cmd>cmd text</cmd>
          <info>
            <p>info</p>
          </info>
        </step>
        <stepsection>
          <p>between</p>
        </stepsection>
        <step>
          <cmd>cmd </cmd>
          <info>
            <note>first in info</note>
            <note>second in info</note>
            <p>info</p>
          </info>
        </step>
        <step>
          <cmd> cmd text </cmd>
          <info>
            <p>info</p>
          </info>
        </step>
        <step>
          <cmd>Choose one of the following:</cmd>
          <choices>
            <choice>substep 1</choice>
            <choice>substep 2</choice>
          </choices>
        </step>
      </steps>
      <result>
        <p>results</p>
      </result>

    </taskbody>
  </task>
  END

    my $ref = Data::Edit::Xml::new(<<END);
  <reference id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
      <title>Testing the S3 Feature for PM 4 1</title>
      <refbody>
          <section>
              <p>To test the S# feature:</p>
              <ol>
                  <li>
                      <p>Set the PCIe link state to L1.2.</p>
                  </li>
                  <li>
                      <p>Issue the command: PM 4 1 command.</p>
                  </li>
              </ol>
          </section>
      </refbody>
  </reference>
  END

    my $concept = $ref->ditaConvertReferenceToConcept;

    ok -p $concept eq <<END;
  <concept id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <conbody>
      <p>To test the S# feature:</p>
      <ol>
        <li>
          <p>Set the PCIe link state to L1.2.</p>
        </li>
        <li>
          <p>Issue the command: PM 4 1 command.</p>
        </li>
      </ol>
    </conbody>
  </concept>
  END

    ok $concept->ditaCouldConvertConceptToTask;

    my $task = $concept->ditaConvertConceptToTask;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $task eq <<END
  <task id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <taskbody>
      <context>
        <p>To test the S# feature:</p>
      </context>
      <steps>
        <step>
          <cmd>Set the PCIe link state to L1.2.</cmd>
        </step>
        <step>
          <cmd>Issue the command: PM 4 1 command.</cmd>
        </step>
      </steps>
      <result/>
    </taskbody>
  </task>
  END

ct is a synonym for ditaConvertConceptToTask.

ditaConvertReferenceToConcept($reference)

Convert a Dita reference to a concept by unwrapping sections. Return undef if the conversion is not possible because there are no ol else return the specified $reference as as concept.

     Parameter   Description
  1  $reference  Reference

Example:

    my $ref = Data::Edit::Xml::new(<<END);
  <reference id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
      <title>Testing the S3 Feature for PM 4 1</title>
      <refbody>
          <section>
              <p>To test the S# feature:</p>
              <ol>
                  <li>
                      <p>Set the PCIe link state to L1.2.</p>
                  </li>
                  <li>
                      <p>Issue the command: PM 4 1 command.</p>
                  </li>
              </ol>
          </section>
      </refbody>
  </reference>
  END


    my $concept = $ref->ditaConvertReferenceToConcept;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $concept eq <<END;
  <concept id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <conbody>
      <p>To test the S# feature:</p>
      <ol>
        <li>
          <p>Set the PCIe link state to L1.2.</p>
        </li>
        <li>
          <p>Issue the command: PM 4 1 command.</p>
        </li>
      </ol>
    </conbody>
  </concept>
  END

    ok $concept->ditaCouldConvertConceptToTask;
    my $task = $concept->ditaConvertConceptToTask;

    ok -p $task eq <<END
  <task id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <taskbody>
      <context>
        <p>To test the S# feature:</p>
      </context>
      <steps>
        <step>
          <cmd>Set the PCIe link state to L1.2.</cmd>
        </step>
        <step>
          <cmd>Issue the command: PM 4 1 command.</cmd>
        </step>
      </steps>
      <result/>
    </taskbody>
  </task>
  END

ditaConvertReferenceToTask($reference)

Convert a Dita reference to a task in situ by representing ol as steps. Return undef if the conversion is not possible because there are no such ol else return the specified $reference as as task.

     Parameter   Description
  1  $reference  Reference

Example:

    my $ref = Data::Edit::Xml::new(<<END);
  <reference id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
      <title>Testing the S3 Feature for PM 4 1</title>
      <refbody>
          <section>
              <p>To test the S# feature:</p>
              <ol>
                  <li>
                      <p>Set the PCIe link state to L1.2.</p>
                  </li>
                  <li>
                      <p>Issue the command: PM 4 1 command.</p>
                  </li>
              </ol>
          </section>
      </refbody>
  </reference>
  END


    my $task = $ref->ditaConvertReferenceToTask;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $task eq <<END
  <task id="GUID-0cab6472-6f2a-e46a-9b6d-16649416ab53">
    <title>Testing the S3 Feature for PM 4 1</title>
    <taskbody>
      <context>
        <p>To test the S# feature:</p>
      </context>
      <steps>
        <step>
          <cmd>Set the PCIe link state to L1.2.</cmd>
        </step>
        <step>
          <cmd>Issue the command: PM 4 1 command.</cmd>
        </step>
      </steps>
      <result/>
    </taskbody>
  </task>
  END

ditaConvertConceptToReference($concept)

Convert a Dita concept to a reference. Return undef if the conversion is not possible else return the specified $concept as as reference.

     Parameter  Description
  1  $concept   Concept

Example:

    my $c = Data::Edit::Xml::new(<<END);
  <concept id="c1">
    <title>Title Text</title>
    <conbody>
      <p>Concept 11</p>
      <section>
        <p>A section 11</p>
      </section>
      <section>
        <p>A section 22</p>
      </section>
      <p>Concept 222</p>
    </conbody>
  </concept>
  END


    my $r = $c->ditaConvertConceptToReference;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $c eq <<END;
  <reference id="c1">
    <title>Title Text</title>
    <refbody>
      <section>
        <p>Concept 11</p>
      </section>
      <section>
        <p>A section 11</p>
      </section>
      <section>
        <p>A section 22</p>
      </section>
      <section>
        <p>Concept 222</p>
      </section>
    </refbody>
  </reference>
  END

    my $C = $c->ditaConvertReferenceToConcept;
    ok -p $C eq <<END;
  <concept id="c1">
    <title>Title Text</title>
    <conbody>
      <p>Concept 11</p>
      <p>A section 11</p>
      <p>A section 22</p>
      <p>Concept 222</p>
    </conbody>
  </concept>
  END

    ok !$C->ditaCouldConvertConceptToTask;

ditaConvertTopicToTask($x)

Convert a topic that is not already a task into a task

     Parameter  Description
  1  $x         Topic parse tree

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <concept id="c1">
    <title/>
    <conbody>
      <p>results</p>
      <ol><li/>Click</ol>
    </conbody>
  </concept>
  END


   $a->ditaConvertTopicToTask;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


   ok nws(-p $a) eq nws(<<END);
  <task id="c1">
    <title/>
    <taskbody>
      <context>
        <p>results</p>
      </context>
      <steps>
        <step>
          <cmd/>
        </step>
  Click
      </steps>
      <result/>
    </taskbody>
  </task>
  END

ditaConvertSectionToConcept($section)

Convert a Dita $section to a concept. Return undef if the conversion is not possible else return the specified $section as as concept.

     Parameter  Description
  1  $section   Section

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <section id="a">
    <title>title</title>
    <p>text</p>
  </section>
  END


    ok -p $a->ditaConvertSectionToConcept eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <concept id="a">
    <title>title</title>
    <conbody>
      <p>text</p>
    </conbody>
  </concept>
  END

    ok -p $a->ditaConvertConceptToSection eq <<END;
  <section id="a">
    <title>title</title>
    <p>text</p>
  </section>
  END

sc is a synonym for ditaConvertSectionToConcept.

ditaConvertConceptToSection($concept)

Convert a Dita concept to a $section . Return undef if the conversion is not possible else return the specified $section as as concept.

     Parameter  Description
  1  $concept   Section

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <section id="a">
    <title>title</title>
    <p>text</p>
  </section>
  END

    ok -p $a->ditaConvertSectionToConcept eq <<END;
  <concept id="a">
    <title>title</title>
    <conbody>
      <p>text</p>
    </conbody>
  </concept>
  END


    ok -p $a->ditaConvertConceptToSection eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <section id="a">
    <title>title</title>
    <p>text</p>
  </section>
  END

cs is a synonym for ditaConvertConceptToSection.

ditaConvertSectionToReference($section)

Convert a Dita $section to a reference. Return undef if the conversion is not possible else return the specified $section as as reference.

     Parameter  Description
  1  $section   Section

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <section id="a">
    <title>title</title>
    <p>text</p>
  </section>
  END


    ok -p $a->ditaConvertSectionToReference eq <<END  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <reference id="a">
    <title>title</title>
    <refbody>
      <section>
        <p>text</p>
      </section>
    </refbody>
  </reference>
  END

ditaConvertSectionToTask($section)

Convert a Dita $section to a task. Return undef if the conversion is not possible else return the specified $section as as task.

     Parameter  Description
  1  $section   Section

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <section id="a">
    <title>title</title>
    <ol>
      <li>step1</li>
      <li>step2</li>
    </ol>
  </section>
  END


    ok -p $a->ditaConvertSectionToTask eq <<END  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <task id="a">
    <title>title</title>
    <taskbody>
      <context/>
      <steps>
        <step>
          <cmd>step1</cmd>
        </step>
        <step>
          <cmd>step2</cmd>
        </step>
      </steps>
      <result/>
    </taskbody>
  </task>
  END

ditaObviousChanges($node)

Make obvious changes to a parse tree to make it look more like Dita.

     Parameter  Description
  1  $node      Node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <dita>
    <ol>
      <li><para>aaa</para></li>
      <li><para>bbb</para></li>
    </ol>
  </dita>
  END


    $a->ditaObviousChanges;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <dita>
    <ol>
      <li>
        <p>aaa</p>
      </li>
      <li>
        <p>bbb</p>
      </li>
    </ol>
  </dita>
  END

ditaXrefs($x)

Make obvious changes to all the xrefs found in a parse tree to make them more useful in Dita.

     Parameter  Description
  1  $x         Parse tree

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <body>
   <xref href="http://www.org">a</xref>
  </body>
  END


    $a->ditaXrefs;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <body>
    <p>
      <xref format="html" href="http://www.org" scope="external">a</xref>
    </p>
  </body>
  END

ditaSampleConcept(@options)

Sample concept

     Parameter  Description
  1  @options   Options for concept

Example:

    ok Data::Edit::Xml::ditaSampleConcept  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     (title=>q(New Concept),
     )->prettyString eq <<END;
  <concept id="GUID-a5405560-67e7-0cd1-9188-9a2546d13a37">
    <title id="title">New Concept</title>
    <conbody>
      <p>Please provide the body of this concept using the body keyword</p>
    </conbody>
  </concept>
  END

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::ditaSampleConcept

ditaSampleTask(@options)

Sample task

     Parameter  Description
  1  @options   Options for task

Example:

    ok Data::Edit::Xml::ditaSampleTask  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     (title=>q(New Task),
     )->prettyString eq <<END;
  <task id="GUID-2ac5c2a6-2475-d5d4-4ce6-d68fdf2102e3">
    <title id="title">New Task</title>
    <taskbody>
      <context/>
      <steps/>
      <result/>
    </taskbody>
  </task>
  END

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::ditaSampleTask

ditaSampleBookMap(@options)

Sample bookmap

     Parameter  Description
  1  @options   Options for bookmap

Example:

    my $a = Data::Edit::Xml::ditaSampleBookMap  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     (author=>q(mim),
      chapters=>Data::Edit::Xml::new(<<END));
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    ok $a->isADitaMap;
    ok !$a->first->isADitaMap;

    ok -p $a eq <<END;
  <bookmap id="GUID-3b04e859-bc04-ac2d-e4bb-f0f99b2a8f90">
    <booktitle>
      <mainbooktitle/>
    </booktitle>
    <bookmeta>
      <shortdesc/>
      <author>mim</author>
      <source/>
      <category/>
      <keywords>
        <keyword/>
      </keywords>
      <prodinfo>
        <prodname product=""/>
        <vrmlist>
          <vrm version=""/>
        </vrmlist>
        <prognum/>
        <brand/>
      </prodinfo>
      <bookchangehistory>
        <approved>
          <revisionid/>
        </approved>
      </bookchangehistory>
      <bookrights>
        <copyrfirst>
          <year/>
        </copyrfirst>
        <bookowner/>
      </bookrights>
    </bookmeta>
    <frontmatter>
      <notices/>
      <booklists>
        <toc/>
      </booklists>
      <preface/>
    </frontmatter>
    <a>
      <b>
        <c/>
      </b>
    </a>
    <appendices/>
    <reltable>
      <relheader>
        <relcolspec/>
        <relcolspec/>
      </relheader>
      <relrow>
        <relcell/>
        <relcell/>
      </relrow>
      <relrow>
        <relcell/>
        <relcell/>
      </relrow>
    </reltable>
  </bookmap>
  END

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::ditaSampleBookMap

isADitaMap($node)

Return the specified $node if this node is a Dita map else return undef

     Parameter  Description
  1  $node      Node to test

Example:

    my $a = Data::Edit::Xml::ditaSampleBookMap
     (author=>q(mim),
      chapters=>Data::Edit::Xml::new(<<END));
  <a>
    <b>
      <c/>
    </b>
  </a>
  END


    ok $a->isADitaMap;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$a->first->isADitaMap;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <bookmap id="GUID-3b04e859-bc04-ac2d-e4bb-f0f99b2a8f90">
    <booktitle>
      <mainbooktitle/>
    </booktitle>
    <bookmeta>
      <shortdesc/>
      <author>mim</author>
      <source/>
      <category/>
      <keywords>
        <keyword/>
      </keywords>
      <prodinfo>
        <prodname product=""/>
        <vrmlist>
          <vrm version=""/>
        </vrmlist>
        <prognum/>
        <brand/>
      </prodinfo>
      <bookchangehistory>
        <approved>
          <revisionid/>
        </approved>
      </bookchangehistory>
      <bookrights>
        <copyrfirst>
          <year/>
        </copyrfirst>
        <bookowner/>
      </bookrights>
    </bookmeta>
    <frontmatter>
      <notices/>
      <booklists>
        <toc/>
      </booklists>
      <preface/>
    </frontmatter>
    <a>
      <b>
        <c/>
      </b>
    </a>
    <appendices/>
    <reltable>
      <relheader>
        <relcolspec/>
        <relcolspec/>
      </relheader>
      <relrow>
        <relcell/>
        <relcell/>
      </relrow>
      <relrow>
        <relcell/>
        <relcell/>
      </relrow>
    </reltable>
  </bookmap>
  END

ditaRoot($node)

Return the specified $node if it a Dita root node else return undef.

     Parameter  Description
  1  $node      Node to check

Example:

    my $a = Data::Edit::Xml::new(q(<concept><a/></concept>));

    ok  $a->ditaRoot;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok !$a->first->ditaRoot;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

ditaTopicHeaders($node, $String)

Add Xml headers for the dita document type indicated by the specified parse tree

     Parameter  Description
  1  $node      Node in parse tree
  2  $String    Suffix string

Example:

    ok Data::Edit::Xml::new(q(<concept/>))->ditaTopicHeaders eq <<END;              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd" []>
  END

ditaPrettyPrintWithHeaders($node)

Add Xml headers for the dita document type indicated by the specified parse tree to a pretty print of the parse tree.

     Parameter  Description
  1  $node      Node in parse tree

Example:

  if (1)
   {my $a = Data::Edit::Xml::new(q(<concept/>));


    ok $a->ditaPrettyPrintWithHeaders eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd" []>
  <concept/>
  END
   }

ditaCutTopicmetaFromAClassificationMap($node, @context)

Remove a topicmeta node from a classification map. Dita::Validate was built from conventional maps and so does not recognize all the situations where topicmeta is invalid in a classification map

     Parameter  Description
  1  $node      Node
  2  @context   Optional context

ditaAddTopicReport($tree, $report)

Place a report into a dita topic using required clean up

     Parameter  Description
  1  $tree      Topic
  2  $report    Report

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <task id="c1">
    <title/>
    <taskbody>
    </taskbody>
  </task>
  END


    $a->ditaAddTopicReport(q(Please note the following discrepancies));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok -p $a eq <<END;
  <task id="c1">
    <title/>
    <taskbody>
      <context>
        <required-cleanup>Please note the following discrepancies</required-cleanup>
      </context>
    </taskbody>
  </task>
  END

help($node)

Get help for a node and the editor

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <steps/>
    <dd/>
  </a>
  END


    my $u = $a->go_dd->help;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $u =~ m(\Ahttp://docs.oasis-open.org/dita/dita/v1.3/errata02/os/complete/part3-all-inclusive/contentmodels/cmltd.html#cmltd__dd\Z);


    my $U = $a->go_steps->help;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $U =~ m(\Ahttp://docs.oasis-open.org/dita/dita/v1.3/errata02/os/complete/part3-all-inclusive/contentmodels/cmlts.html#cmlts__steps\Z);

h is a synonym for help.

Html and word conversions

Methods useful for converting Word and HTML to Dita

htmlHeadersToSections($tree)

Position sections just before html header tags so that subsequently the document can be divided into sections.

     Parameter  Description
  1  $tree      Parse tree

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
  <h1>h1</h1>
    H1
  <h2>h2</h2>
    H2
  <h3>h3</h3>
    H3
  <h3>h3</h3>
    H3
  <h2>h2</h2>
    H2
  <h4>h4</h4>
    H4
  </x>
  END


  $x->htmlHeadersToSections;                                                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    $x->divideDocumentIntoSections(sub

     {my ($topicref, $section) = @_;

      my $file = keys %file;

      $topicref->href = $file;

      $file{$file} = -p $section;

      $section->cut;

     });

    ok -p $x eq <<END;
  <x>
    <topicref href="0">
      <topicref href="1">
        <topicref href="2"/>
        <topicref href="3"/>
      </topicref>
      <topicref href="4">
        <topicref href="5"/>
      </topicref>
    </topicref>
  </x>
  END

divideDocumentIntoSections($node, $cutSub)

Divide a parse tree into sections by moving non section tags into their corresponding section so that the section tags expand until they are contiguous. The sections are then cut out by applying the specified sub to each section tag in the parse tree. The specified sub will receive the containing topicref and the section to be cut out as parameters allowing a reference to the cut out section to be inserted into the topicref.

     Parameter  Description
  1  $node      Parse tree
  2  $cutSub    Cut out sub

Example:

   {my $x = Data::Edit::Xml::new(<<END);
  <x>
  <h1>h1</h1>
    H1
  <h2>h2</h2>
    H2
  <h3>h3</h3>
    H3
  <h3>h3</h3>
    H3
  <h2>h2</h2>
    H2
  <h4>h4</h4>
    H4
  </x>
  END

  $x->htmlHeadersToSections;


    $x->divideDocumentIntoSections(sub                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


     {my ($topicref, $section) = @_;

      my $file = keys %file;

      $topicref->href = $file;

      $file{$file} = -p $section;

      $section->cut;

     });

    ok -p $x eq <<END;
  <x>
    <topicref href="0">
      <topicref href="1">
        <topicref href="2"/>
        <topicref href="3"/>
      </topicref>
      <topicref href="4">
        <topicref href="5"/>
      </topicref>
    </topicref>
  </x>
  END

divideHtmlDocumentIntoSections($tree)

Divide a parse tree representing an html document into sections based on the heading tags.

     Parameter  Description
  1  $tree      Parse tree

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <h1>HH11</h1>    text1
      <h2>HH22</h2>  text2
      <h2>HH22</h2>  text3
        <h4>HH44</h4>text4
      <h1>HH11</h1>  text5
  </a>
  END


    $a->divideHtmlDocumentIntoSections;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok nws(-p $a) eq nws(<<END);
  <a>
    <section outputclass="1">
      <title>HH11</title>
  text1
      <section outputclass="2">
        <title>HH22</title>
  text2
      </section>
      <section outputclass="2">
        <title>HH22</title>
  text3
        <section outputclass="4">
          <title>HH44</title>
  text4
        </section>
      </section>
    </section>
    <section outputclass="1">
      <title>HH11</title>
  text5
    </section>
  </a>
  END

ditaParagraphToNote($node, $wrapNoteContentWithParagaph)

Convert all <p> nodes to <note> if the paragraph starts with 'Note:', optionally wrapping the content of the <note> with a <p>

     Parameter                     Description
  1  $node                         Parse tree
  2  $wrapNoteContentWithParagaph  Wrap the <note> content with a <p> if true

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <p> Note: see over for details.</p>
  </a>
  END


    $a->ditaParagraphToNote(1);                                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <a>
    <note>
      <p>See over for details.</p>
    </note>
  </a>
  END

wordStyles($x)

Extract style information from a parse tree representing a word document.

     Parameter  Description
  1  $x         Parse tree

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
   <text:list-style style:name="aa">
     <text:list-level-style-bullet text:level="2"/>
   </text:list-style>
  </a>
  END


    my $styles = $a->wordStyles;                                                    # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply $styles, {bulletedList=>{aa=>{2=>1}}};

htmlTableToDita($table)

Convert an "html table" to a Dita table.

     Parameter  Description
  1  $table     Html table node

Example:

   {my $a = Data::Edit::Xml::new(<<END);
   <table>
     <thead>
      <tr>
         <th>Month</th>
         <th>Savings</th>
         <th>Phone</th>
         <th>Comment</th>
      </tr>
     </thead>
     <tbody>
      <tr>
         <td>January</td>
         <td>100</td>
         <td>555-1212</td>
      </tr>
      <tr>
         <td>February</td>
         <td>80</td>
      </tr>
     </tbody>
  </table>
  END


    $a->htmlTableToDita;                                                            # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <table>
    <tgroup cols="4">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <colspec colname="c3" colnum="3" colwidth="1*"/>
      <colspec colname="c4" colnum="4" colwidth="1*"/>
      <thead>
        <row>
          <entry>Month</entry>
          <entry>Savings</entry>
          <entry>Phone</entry>
          <entry>Comment</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>January</entry>
          <entry>100</entry>
          <entry nameend="c4" namest="c3">555-1212</entry>
        </row>
        <row>
          <entry>February</entry>
          <entry nameend="c4" namest="c2">80</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

ditaSyntaxDiagramFromDocBookCmdSynopsis({package ditaSyntaxDiagramFromDocBookCmdSynopsis;)

Convert doc book cmdsynopsis to Dita syntax diagram

     Parameter                                          Description
  1  {package ditaSyntaxDiagramFromDocBookCmdSynopsis;  Allows us to package the entire conversion as one method

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <cmdsynopsis>
    <command>fs</command>
    <arg choice="plain">list</arg>
    <group choice="opt">
      <arg choice="plain">--pending</arg>
      <arg choice="plain">--running</arg>
    </group>
    <group choice="opt">
      <arg choice="plain">--online</arg>
      <arg choice="plain">
        --offline
        <group choice="req">
          <arg choice="plain">http</arg>
          <arg choice="plain">https</arg>
          <arg choice="plain">ftp</arg>
          <arg choice="plain">ssh</arg>
        </group>
      </arg>
      <arg choice="plain">--special</arg>
      <arg choice="plain">--snap</arg>
    </group>
    <group choice="opt">
      <arg choice="plain">--real</arg>
      <arg choice="plain">--virtual</arg>
      <arg choice="plain">--absolute</arg>
    </group>
    <arg choice="opt">--titled</arg>
    <group choice="opt">
      <arg choice="plain">--total</arg>
      <arg choice="plain">--space</arg>
    </group>
    <arg choice="opt">
      --rename
      <replaceable>new-name</replaceable>
    </arg>
    <arg choice="opt">
      --sort
      <replaceable>sort procedure</replaceable>
    </arg>
    <arg choice="opt">--raw</arg>
    <arg choice="opt">
      --limit
      <replaceable>limits</replaceable>
    </arg>
    <arg choice="opt">--page</arg>
    <arg choice="opt" rep="repeat">
      <replaceable>files</replaceable>
    </arg>
  </cmdsynopsis>
  END


    $a->ditaSyntaxDiagramFromDocBookCmdSynopsis;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok -p $a eq <<END;
  <syntaxdiagram>
    <groupseq>
      <kwd outputclass="command">fs</kwd>
      <kwd>list</kwd>
      <groupchoice importance="optional">
        <kwd>--pending</kwd>
        <kwd>--running</kwd>
      </groupchoice>
      <groupchoice importance="optional">
        <kwd>--online</kwd>
        <groupseq>
          <kwd>
        --offline
        </kwd>
          <groupchoice>
            <kwd>http</kwd>
            <kwd>https</kwd>
            <kwd>ftp</kwd>
            <kwd>ssh</kwd>
          </groupchoice>
        </groupseq>
        <kwd>--special</kwd>
        <kwd>--snap</kwd>
      </groupchoice>
      <groupchoice importance="optional">
        <kwd>--real</kwd>
        <kwd>--virtual</kwd>
        <kwd>--absolute</kwd>
      </groupchoice>
      <kwd importance="optional">--titled</kwd>
      <groupchoice importance="optional">
        <kwd>--total</kwd>
        <kwd>--space</kwd>
      </groupchoice>
      <groupseq importance="optional">
        <kwd>
      --rename
      </kwd>
        <var>new-name</var>
      </groupseq>
      <groupseq importance="optional">
        <kwd>
      --sort
      </kwd>
        <var>sort procedure</var>
      </groupseq>
      <kwd importance="optional">--raw</kwd>
      <groupseq importance="optional">
        <kwd>
      --limit
      </kwd>
        <var>limits</var>
      </groupseq>
      <kwd importance="optional">--page</kwd>
      <groupseq importance="optional">
        <var>files</var>
        <sep>…</sep>
      </groupseq>
    </groupseq>
  </syntaxdiagram>
  END

    $a->ditaSyntaxDiagramToBasicRepresentation;

    ok nws(-p $a) eq nws(<<END);
  <p>
    <cmdname>fs</cmdname>
    <codeph>list</codeph>

   [ <codeph>--pending</codeph> | <codeph>--running</codeph> ]

   [ <codeph>--online</codeph> |
     <codeph> --offline </codeph> { <codeph>http</codeph> | <codeph>https</codeph>  | <codeph>ftp</codeph>  | <codeph>ssh</codeph> }  |
     <codeph>--special</codeph> |
     <codeph>--snap</codeph>
   ]

   [ <codeph>--real</codeph> |
     <codeph>--virtual</codeph> |
     <codeph>--absolute</codeph>
   ]

   [ <codeph>--titled</codeph> ]
   [ <codeph>--total</codeph>  |  <codeph>--space</codeph> ]
   [ <codeph> --rename </codeph>  <userinput>new-name</userinput> ]
   [ <codeph> --sort </codeph>    <userinput>sort procedure</userinput> ]
   [ <codeph>--raw</codeph> ]
   [ <codeph> --limit </codeph>     <userinput>limits</userinput> ]
   [ <codeph>--page</codeph>  ]
   [ <userinput>files</userinput> <codeph>…</codeph> ]
  </p>
  END

ditaSyntaxDiagramToBasicRepresentation($x)

Convert Dita syntax diagrams into Micaela's Basic Version.

     Parameter  Description
  1  $x         Parse tree

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <cmdsynopsis>
    <command>fs</command>
    <arg choice="plain">list</arg>
    <group choice="opt">
      <arg choice="plain">--pending</arg>
      <arg choice="plain">--running</arg>
    </group>
    <group choice="opt">
      <arg choice="plain">--online</arg>
      <arg choice="plain">
        --offline
        <group choice="req">
          <arg choice="plain">http</arg>
          <arg choice="plain">https</arg>
          <arg choice="plain">ftp</arg>
          <arg choice="plain">ssh</arg>
        </group>
      </arg>
      <arg choice="plain">--special</arg>
      <arg choice="plain">--snap</arg>
    </group>
    <group choice="opt">
      <arg choice="plain">--real</arg>
      <arg choice="plain">--virtual</arg>
      <arg choice="plain">--absolute</arg>
    </group>
    <arg choice="opt">--titled</arg>
    <group choice="opt">
      <arg choice="plain">--total</arg>
      <arg choice="plain">--space</arg>
    </group>
    <arg choice="opt">
      --rename
      <replaceable>new-name</replaceable>
    </arg>
    <arg choice="opt">
      --sort
      <replaceable>sort procedure</replaceable>
    </arg>
    <arg choice="opt">--raw</arg>
    <arg choice="opt">
      --limit
      <replaceable>limits</replaceable>
    </arg>
    <arg choice="opt">--page</arg>
    <arg choice="opt" rep="repeat">
      <replaceable>files</replaceable>
    </arg>
  </cmdsynopsis>
  END

    $a->ditaSyntaxDiagramFromDocBookCmdSynopsis;

    ok -p $a eq <<END;
  <syntaxdiagram>
    <groupseq>
      <kwd outputclass="command">fs</kwd>
      <kwd>list</kwd>
      <groupchoice importance="optional">
        <kwd>--pending</kwd>
        <kwd>--running</kwd>
      </groupchoice>
      <groupchoice importance="optional">
        <kwd>--online</kwd>
        <groupseq>
          <kwd>
        --offline
        </kwd>
          <groupchoice>
            <kwd>http</kwd>
            <kwd>https</kwd>
            <kwd>ftp</kwd>
            <kwd>ssh</kwd>
          </groupchoice>
        </groupseq>
        <kwd>--special</kwd>
        <kwd>--snap</kwd>
      </groupchoice>
      <groupchoice importance="optional">
        <kwd>--real</kwd>
        <kwd>--virtual</kwd>
        <kwd>--absolute</kwd>
      </groupchoice>
      <kwd importance="optional">--titled</kwd>
      <groupchoice importance="optional">
        <kwd>--total</kwd>
        <kwd>--space</kwd>
      </groupchoice>
      <groupseq importance="optional">
        <kwd>
      --rename
      </kwd>
        <var>new-name</var>
      </groupseq>
      <groupseq importance="optional">
        <kwd>
      --sort
      </kwd>
        <var>sort procedure</var>
      </groupseq>
      <kwd importance="optional">--raw</kwd>
      <groupseq importance="optional">
        <kwd>
      --limit
      </kwd>
        <var>limits</var>
      </groupseq>
      <kwd importance="optional">--page</kwd>
      <groupseq importance="optional">
        <var>files</var>
        <sep>…</sep>
      </groupseq>
    </groupseq>
  </syntaxdiagram>
  END


    $a->ditaSyntaxDiagramToBasicRepresentation;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok nws(-p $a) eq nws(<<END);
  <p>
    <cmdname>fs</cmdname>
    <codeph>list</codeph>

   [ <codeph>--pending</codeph> | <codeph>--running</codeph> ]

   [ <codeph>--online</codeph> |
     <codeph> --offline </codeph> { <codeph>http</codeph> | <codeph>https</codeph>  | <codeph>ftp</codeph>  | <codeph>ssh</codeph> }  |
     <codeph>--special</codeph> |
     <codeph>--snap</codeph>
   ]

   [ <codeph>--real</codeph> |
     <codeph>--virtual</codeph> |
     <codeph>--absolute</codeph>
   ]

   [ <codeph>--titled</codeph> ]
   [ <codeph>--total</codeph>  |  <codeph>--space</codeph> ]
   [ <codeph> --rename </codeph>  <userinput>new-name</userinput> ]
   [ <codeph> --sort </codeph>    <userinput>sort procedure</userinput> ]
   [ <codeph>--raw</codeph> ]
   [ <codeph> --limit </codeph>     <userinput>limits</userinput> ]
   [ <codeph>--page</codeph>  ]
   [ <userinput>files</userinput> <codeph>…</codeph> ]
  </p>
  END

ditaWrapWithPUnderConbody($conbody)

Wrap items immediately under Dita conbody with p or merge with any previous p if the item in question does not fit under conbody but does fit under p. Return the current node if it is conbody else return undef.

     Parameter  Description
  1  $conbody   Section

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <conbody>text<q>quote</q><p>new paragraph</p>
  more text</conbody>
  END


    $a->ditaWrapWithPUnderConbody;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $b = new(<<END);
  <conbody><p>text<q>quote</q></p><p>new paragraph
  more text</p></conbody>
  END

    ok $a->equals($b);

PCD

Please Change Dita Language Features

putNodeAs($node, $name, @context)

Return the specified $node after saving it under the specified $name if we are in the optional @context.

     Parameter  Description
  1  $node      Node
  2  $name      Save name
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END

    my ($d, $c, $b) = $a->byList;


    $d->putNodeAs(q(D));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok $a->getNodeAs(q(D)) == $d;
    %Data::Edit::Xml::savedNodes = ();
    ok $a->getNodeAs(q(D)) == $a;

    ok $a->reportNode_AAAA eq <<END;
  AAAA
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END
    ok $d->reportNodeAttributes_BBBB eq q(BBBB  id="d");
    ok $d->reportNodeAttributes_CCCC eq q(CCCC  id="d");
    ok $d->reportNodeContext_DDDD    eq q(DDDD d c b a);

put is a synonym for putNodeAs.

getNodeAs($node, $name, @context)

Return the specified $node unless it is possible to return the node saved with putNodeAs under the specified name and we are optionally in the specified @context.

     Parameter  Description
  1  $node      Default node
  2  $name      Name of saved node
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END

    my ($d, $c, $b) = $a->byList;

    $d->putNodeAs(q(D));

    ok $a->getNodeAs(q(D)) == $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    %Data::Edit::Xml::savedNodes = ();

    ok $a->getNodeAs(q(D)) == $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $a->reportNode_AAAA eq <<END;
  AAAA
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END
    ok $d->reportNodeAttributes_BBBB eq q(BBBB  id="d");
    ok $d->reportNodeAttributes_CCCC eq q(CCCC  id="d");
    ok $d->reportNodeContext_DDDD    eq q(DDDD d c b a);

get is a synonym for getNodeAs.

reportNodeAttributes($node, $label, @context)

Print the attributes of the specified $node identified by the specified $label if we are in the optional @context.

     Parameter  Description
  1  $node      Node node
  2  $label     Label
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END

    my ($d, $c, $b) = $a->byList;

    $d->putNodeAs(q(D));
    ok $a->getNodeAs(q(D)) == $d;
    %Data::Edit::Xml::savedNodes = ();
    ok $a->getNodeAs(q(D)) == $a;

    ok $a->reportNode_AAAA eq <<END;
  AAAA
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END
    ok $d->reportNodeAttributes_BBBB eq q(BBBB  id="d");
    ok $d->reportNodeAttributes_CCCC eq q(CCCC  id="d");
    ok $d->reportNodeContext_DDDD    eq q(DDDD d c b a);

rna is a synonym for reportNodeAttributes.

reportNodeContext($node, $label, @context)

Print the context of the specified $node identified by the specified $label if we are in the optional @context.

     Parameter  Description
  1  $node      Node node
  2  $label     Label
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END

    my ($d, $c, $b) = $a->byList;

    $d->putNodeAs(q(D));
    ok $a->getNodeAs(q(D)) == $d;
    %Data::Edit::Xml::savedNodes = ();
    ok $a->getNodeAs(q(D)) == $a;

    ok $a->reportNode_AAAA eq <<END;
  AAAA
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END
    ok $d->reportNodeAttributes_BBBB eq q(BBBB  id="d");
    ok $d->reportNodeAttributes_CCCC eq q(CCCC  id="d");
    ok $d->reportNodeContext_DDDD    eq q(DDDD d c b a);

rnc is a synonym for reportNodeContext.

reportNode($node, $label, @context)

Print the parse tree starting at the specified $node identified by the specified $label if we are in the optional @context.

     Parameter  Description
  1  $node      Node node
  2  $label     Label
  3  @context   Optional context

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END

    my ($d, $c, $b) = $a->byList;

    $d->putNodeAs(q(D));
    ok $a->getNodeAs(q(D)) == $d;
    %Data::Edit::Xml::savedNodes = ();
    ok $a->getNodeAs(q(D)) == $a;

    ok $a->reportNode_AAAA eq <<END;
  AAAA
  <a>
    <b>
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END
    ok $d->reportNodeAttributes_BBBB eq q(BBBB  id="d");
    ok $d->reportNodeAttributes_CCCC eq q(CCCC  id="d");
    ok $d->reportNodeContext_DDDD    eq q(DDDD d c b a);

rn is a synonym for reportNode.

Debug

Debugging methods

sss($node, @text)

Put, after the current $node, the specified @text and return the current $node.

     Parameter  Description
  1  $node      Node
  2  @text      Text

Example:

    my $a = Data::Edit::Xml::new(q(<a><b><c/></b></a>));

    $a->go_b_c__sss_aa_bb_cc;

    ok -p $a eq <<END;
  <a>
    <b>
      <c/>
  aa bb cc
    </b>
  </a>
  END

printAttributes($node)

Print the attributes of a node.

     Parameter  Description
  1  $node      Node whose attributes are to be printed.

Example:

    my $x = Data::Edit::Xml::new(my $s = <<END);
  <a no="1" word="first"/>
  END


    ok $x->printAttributes eq qq( no="1" word="first");                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

printAttributesHtml($node)

Print the attributes of a node as html.

     Parameter  Description
  1  $node      Node whose attributes are to be printed.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a id="1">
    <b id="2" b="B">
      <c/>
    </b>
    <d id="3" d="D">
      Some text
    </d>
  </a>
  END

    ok $a->prettyStringHtml eq <<END;
  <div class="xmlLine"><span class="xmlLineStartTag"></span><span class="xmlLt">&lt;</span><span class="xmlTag">a</span> <span class="xmlAttr">id</span><span class="xmlEquals">=</span><span class="xmlValue">"1"</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLt">&lt;</span><span class="xmlTag">b</span> <span class="xmlAttr">b</span><span class="xmlEquals">=</span><span class="xmlValue">"B"</span> <span class="xmlAttr">id</span><span class="xmlEquals">=</span><span class="xmlValue">"2"</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLt">&lt;</span><span class="xmlTag">c</span><span class="xmlSlashGt">/&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLtSlash">&lt;/</span><span class="xmlTag">b</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="xmlLt">&lt;</span><span class="xmlTag">d</span> <span class="xmlAttr">d</span><span class="xmlEquals">=</span><span class="xmlValue">"D"</span> <span class="xmlAttr">id</span><span class="xmlEquals">=</span><span class="xmlValue">"3"</span><span class="xmlGt">&gt;</span><span class="xmlText">Some text</span><span class="xmlLtSlash">&lt;/</span><span class="xmlTag">d</span><span class="xmlGt">&gt;</span></div>
  <div class="xmlLine"><span class="xmlLineStartTag"></span><span class="xmlLtSlash">&lt;/</span><span class="xmlTag">a</span><span class="xmlGt">&gt;</span></div>
  END

printStack($node, @context)

Print the attributes of a node and each of its parents

     Parameter  Description
  1  $node      Node whose attributes are to be printed
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a id="a">
    <b id="b">
      <c>
        <d id="d"/>
      </c>
    </b>
  </a>
  END

    my $d = $a->firstUntil_d;

    ok $d->printStack eq <<END;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  a id="a"
    b id="b"
      c
        d id="d"
  END
    ok -S $d eq <<END;
  a id="a"
    b id="b"
      c
        d id="d"
  END

printNode($node, @context)

Print the tag and attributes of a node.

     Parameter  Description
  1  $node      Node whose attributes are to be printed
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c id="42" match="mm"/>
    </b>
    <d>
      <e/>
    </d>
  </a>
  END


    ok $c->printNode eq q(c id="42" match="mm");                                     # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

printNodeAsSingleton($node, @context)

Print the tag and attributes of a node as if it were a single node regardless of any child nodes it might have

     Parameter  Description
  1  $node      Node whose attributes are to be printed
  2  @context   Optional context.

Use the optional @context parameter to test the context of the specified $node as understood by method at. If the context is supplied and $node is not in this context then this method returns undef immediately.

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a id="a" outputclass="aa">
    <b/>
  </a>
  END


    ok $a->printNodeAsSingleton eq q(<a id="a" outputclass="aa"/>);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

goFish($node, @path)

A debug version of go that returns additional information explaining any failure to reach the node identified by the path.

Returns ([reachable tag...], failing tag, [possible tag...]) where:

reachable tag

the path elements successfully traversed;

failing tag

the failing element;

possible tag

the possibilities at the point where the path failed if it failed else undef.

Parameters:

     Parameter  Description
  1  $node      Node
  2  @path      Search specification.

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c>
        <d/>
      </c>
      <c/>
    </b>
    <b/>
  </a>
  END


      my ($good, $fail, $possible) = $a->goFish(qw(b c D));                         # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


      ok  $fail eq q(D);

      is_deeply $good,     [qw(b c)];

      is_deeply $possible, [q(d)];

Validation

Validate Xml

checkAllPaths($valid)

Create a representation of all the paths permitted in a block of Xml. The syntax of each line is a word representing an Xml tag followed by one of: tag 1 * + ? - with 1 being the default and meaning that exactly one instance of this tag is required under its parent, * meaning that zero or more such tags are permitted under its parent, + meaning that one or more such tags are required under its parent, ? meaning that no more than one such tag is permitted under its parent, - meaning that this is a leaf tag that can be missing or present just once under its parent. The remaining words on the line being treated as a comment describing the purpose of the tag. Tags that are not marked with - are required to have either text under them if they are leaf tags. Tags marked with - are boolean leafs and may not have any text or child tags under them. The children of a tag are listed on following lines with exactly two more spaces of indentation. This enables the validation of a block of non recursive Xml without having to resort to writing a complex DTD.

     Parameter  Description
  1  $valid     Path descriptions

Example:

    my $paths = <<'END';
  database           The database to be used for the table
    name             The name of the database
    table +          The table to be created
      name           The name of the table
      hide -         Hide this table if present
      column +       Columns in this table
        name         The name of the column
        type         The type of the column
        description  A description of the purpose of the column
        edit ?       A regular expression to edit the column data

      reference *    References from this table
        name         The name of the reference
        table        The name of the referenced table
        description  A description of the reference
      row *          Row of data to be loaded inot the table
        col +        Column value
  END

   is_deeply checkAllPaths($paths),  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    {"name"                        => [1, "name of the database"],
     "table"                       => ["+", "The table to be created"],
     "table column"                => ["+", "Columns in this table"],
     "table column description"    => [1, "description of the purpose of the column"],
     "table column edit"           => ["?", "A regular expression to edit the column data"],
     "table column name"           => [1, "name of the column"],
     "table column type"           => [1, "type of the column"],
     "table hide"                  => ["-", "Hide this table if present"],
     "table name"                  => [1, "name of the table"],
     "table reference"             => ["*", "References from this table"],
     "table reference description" => [1, "description of the reference"],
     "table reference name"        => [1, "name of the reference"],
     "table reference table"       => [1, "name of the referenced table"],
     "table row"                   => ["*", "Row of data to be loaded inot the table"],
     "table row col"               => ["+", "Column value"]
    };

    my $xml = <<'END';
  <database>
    <name>test</name>
    <table>
      <name>team</name>
      <column>   <name>name  </name> <type>varchar(255)</type> <description>Name of the team                  </description></column>
      <column>   <name>age   </name> <type>varchar(8)  </type> <description>Junior or Senior team             </description><edit>qr(\A(junior|senior)\Z)i</edit></column>
      <column>   <name>gender</name> <type>varchar(8)  </type> <description>Female or Male                    </description><edit>qr(\A(female|male)\Z)i  </edit></column>
      <column>   <name>school</name> <type>varchar(255)</type> <description>School attended by team           </description></column>
      <column>   <name>region</name> <type>varchar(255)</type> <description>Region team is located in         </description></column>
      <column>   <name>coach </name> <type>varchar(255)</type> <description>Email address of the coach of this team</description></column>
      <row><col>Lubbock Lions    </col><col>junior</col><col>Female</col><col>Lubbock High         </col><col>North</col><col>ll@coaches.com</col></row>
      <row><col>Titan Tigers     </col><col>junior</col><col>Female</col><col>Titan Senior High    </col><col>East </col><col>tt@coaches.com</col></row>
      <row><col>Saturn Samurai   </col><col>junior</col><col>Male  </col><col>Saturn University    </col><col>West </col><col>ss@coaches.com</col></row>
      <row><col>Jovial Journeymen</col><col>junior</col><col>Male  </col><col>University of Jupiter</col><col>South</col><col>jj@coaches.com</col></row>
    </table>

    <table>
      <name>field</name>
      <column>   <name>name  </name> <type>varchar(255)</type> <description>Name of the field                 </description></column>
      <column>   <name>street</name> <type>varchar(255)</type> <description>Street address of the field       </description></column>
      <column>   <name>city  </name> <type>varchar(255)</type> <description>City containing the field         </description></column>
      <column>   <name>zip   </name> <type>char(9)     </type> <description>Zip code of field                 </description></column>
      <column>   <name>school</name> <type>varchar(255)</type> <description>Email address of the owner of the field  </description></column>
      <row><col>Big Circle   </col><col>1 Elm Street </col><col>Treeville   </col><col>76754</col><col>Lubbock High         </col></row>
      <row><col>Large Field  </col><col>2 Oak Street </col><col>TitusCity   </col><col>76224</col><col>Titan Senior High    </col></row>
      <row><col>Small Diamond</col><col>3 Ash Street </col><col>Ioville     </col><col>72754</col><col>Saturn University    </col></row>
      <row><col>Large Oval   </col><col>4 Pine Street</col><col>GanymedeCity</col><col>76334</col><col>University of Jupiter</col></row>
    </table>

    <table>
      <name>matches</name>
      <column>   <name>date        </name> <type>date         </type> <description>Time of match                     </description></column>
      <column>   <name>score1      </name> <type>int          </type> <description>Goals scored by home team         </description></column>
      <column>   <name>score2      </name> <type>int          </type> <description>Goals scored by away team         </description></column>
      <column>   <name>adminAgree  </name> <type>boolean      </type> <description>true - Admin will allow the match, false - Admin will not allow the match, null - no decision yet</description></column>
      <column>   <name>coachAgree  </name> <type>boolean      </type> <description>true - away coach will allow the match, false - away coach will not allow the match, null - no decision yet</description></column>
      <reference><name>team1       </name> <table>team       </table> <description>The home team</description></reference>
      <reference><name>team2       </name> <table>team       </table> <description>The away team</description></reference>
      <reference><name>field       </name> <table>field      </table> <description>The field on which the match will be played</description></reference>
      <row><col>2020-03-08</col><col>1</col><col>22</col><col>0</col><col>0</col><col>1</col><col>2</col><col>1</col></row>
      <row><col>2020-04-18</col><col>1</col><col>13</col><col>0</col><col>0</col><col>1</col><col>3</col><col>1</col></row>
      <row><col>2020-04-22</col><col>1</col><col>13</col><col>0</col><col>0</col><col>1</col><col>3</col><col>2</col></row>
      <row><col>2020-04-25</col><col>1</col><col>13</col><col>0</col><col>0</col><col>1</col><col>3</col><col>2</col></row>
    </table>

    <table>
      <name>auth</name> <hide/>
      <column>   <name>state     </name> <type>varchar(16) </type>  <description>The unique state number which connects a random number on the browser to a unique github userid on the server </description></column>
      <column>   <name>token     </name> <type>varchar(64) </type>  <description>The token from github                                            </description></column>
      <column>   <name>scope     </name> <type>varchar(255)</type>  <description>The scope from github                                            </description></column>
      <column>   <name>tokenType </name> <type>varchar(16) </type>  <description>The type of token we got from github                             </description></column>
      <column>   <name>avatar_url</name> <type>varchar(255)</type>  <description>https://avatars1.githubusercontent.com/u/7548378?v=4             </description></column>
      <column>   <name>bio       </name> <type>varchar(255)</type>  <description>Biography                                                                 </description></column>
      <column>   <name>blog      </name> <type>varchar(255)</type>  <description>http://www.appaapps.com                                          </description></column>
      <column>   <name>company   </name> <type>varchar(255)</type>  <description>Appa Apps Ltd Inc                                                </description></column>
      <column>   <name>created_at</name> <type>varchar(255)</type>  <description>2014-05-11T11:19:04Z                                             </description></column>
      <column>   <name>email     </name> <type>varchar(255)</type>  <description>philiprbrenan\@gmail.com                                         </description></column>
      <column>   <name>location  </name> <type>varchar(255)</type>  <description>Terra                                                            </description></column>
      <column>   <name>login     </name> <type>varchar(255)</type>  <description>philiprbrenan                                                    </description></column>
      <column>   <name>name      </name> <type>varchar(255)</type>  <description>philip r brenan                                                  </description></column>
    </table>
  </database>
  END

    my $dd = xmlToPerl($xml, $paths);
    my %table  = map {$_->name => $_}                                    $dd->table->@*;
    my %column = map {$_->name => {map {$_->name => $_} $_->column->@*}} $dd->table->@*;

    ok $table{auth}->hide;
    ok $column{matches}{coachAgree}{type} eq q(boolean);
    is_deeply $column{field}{street},
      bless({description => "Street address of the field",
             name        => "street",
             type        => "varchar(255)",
            }, "database::table::column");

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::checkAllPaths

xmlToPerl($xml, $valid)

Parse some Xml, validate using a description recognized by checkAllPaths and return the corresponding Perl structure. Valid fields in the returned structure can be referenced via methods with the same names as their corresponding Xml tags. Tags marked with * or + in the description processed by checkAllPaths result in arrays of children, whilst tags marked with 1 or ? can be referenced directly.

     Parameter  Description
  1  $xml       Xml represented as a string
  2  $valid     Xml validator represented as a string

Example:

    my $paths = <<'END';
  database           The database to be used for the table
    name             The name of the database
    table +          The table to be created
      name           The name of the table
      hide -         Hide this table if present
      column +       Columns in this table
        name         The name of the column
        type         The type of the column
        description  A description of the purpose of the column
        edit ?       A regular expression to edit the column data

      reference *    References from this table
        name         The name of the reference
        table        The name of the referenced table
        description  A description of the reference
      row *          Row of data to be loaded inot the table
        col +        Column value
  END
   is_deeply checkAllPaths($paths),
    {"name"                        => [1, "name of the database"],
     "table"                       => ["+", "The table to be created"],
     "table column"                => ["+", "Columns in this table"],
     "table column description"    => [1, "description of the purpose of the column"],
     "table column edit"           => ["?", "A regular expression to edit the column data"],
     "table column name"           => [1, "name of the column"],
     "table column type"           => [1, "type of the column"],
     "table hide"                  => ["-", "Hide this table if present"],
     "table name"                  => [1, "name of the table"],
     "table reference"             => ["*", "References from this table"],
     "table reference description" => [1, "description of the reference"],
     "table reference name"        => [1, "name of the reference"],
     "table reference table"       => [1, "name of the referenced table"],
     "table row"                   => ["*", "Row of data to be loaded inot the table"],
     "table row col"               => ["+", "Column value"]
    };

    my $xml = <<'END';
  <database>
    <name>test</name>
    <table>
      <name>team</name>
      <column>   <name>name  </name> <type>varchar(255)</type> <description>Name of the team                  </description></column>
      <column>   <name>age   </name> <type>varchar(8)  </type> <description>Junior or Senior team             </description><edit>qr(\A(junior|senior)\Z)i</edit></column>
      <column>   <name>gender</name> <type>varchar(8)  </type> <description>Female or Male                    </description><edit>qr(\A(female|male)\Z)i  </edit></column>
      <column>   <name>school</name> <type>varchar(255)</type> <description>School attended by team           </description></column>
      <column>   <name>region</name> <type>varchar(255)</type> <description>Region team is located in         </description></column>
      <column>   <name>coach </name> <type>varchar(255)</type> <description>Email address of the coach of this team</description></column>
      <row><col>Lubbock Lions    </col><col>junior</col><col>Female</col><col>Lubbock High         </col><col>North</col><col>ll@coaches.com</col></row>
      <row><col>Titan Tigers     </col><col>junior</col><col>Female</col><col>Titan Senior High    </col><col>East </col><col>tt@coaches.com</col></row>
      <row><col>Saturn Samurai   </col><col>junior</col><col>Male  </col><col>Saturn University    </col><col>West </col><col>ss@coaches.com</col></row>
      <row><col>Jovial Journeymen</col><col>junior</col><col>Male  </col><col>University of Jupiter</col><col>South</col><col>jj@coaches.com</col></row>
    </table>

    <table>
      <name>field</name>
      <column>   <name>name  </name> <type>varchar(255)</type> <description>Name of the field                 </description></column>
      <column>   <name>street</name> <type>varchar(255)</type> <description>Street address of the field       </description></column>
      <column>   <name>city  </name> <type>varchar(255)</type> <description>City containing the field         </description></column>
      <column>   <name>zip   </name> <type>char(9)     </type> <description>Zip code of field                 </description></column>
      <column>   <name>school</name> <type>varchar(255)</type> <description>Email address of the owner of the field  </description></column>
      <row><col>Big Circle   </col><col>1 Elm Street </col><col>Treeville   </col><col>76754</col><col>Lubbock High         </col></row>
      <row><col>Large Field  </col><col>2 Oak Street </col><col>TitusCity   </col><col>76224</col><col>Titan Senior High    </col></row>
      <row><col>Small Diamond</col><col>3 Ash Street </col><col>Ioville     </col><col>72754</col><col>Saturn University    </col></row>
      <row><col>Large Oval   </col><col>4 Pine Street</col><col>GanymedeCity</col><col>76334</col><col>University of Jupiter</col></row>
    </table>

    <table>
      <name>matches</name>
      <column>   <name>date        </name> <type>date         </type> <description>Time of match                     </description></column>
      <column>   <name>score1      </name> <type>int          </type> <description>Goals scored by home team         </description></column>
      <column>   <name>score2      </name> <type>int          </type> <description>Goals scored by away team         </description></column>
      <column>   <name>adminAgree  </name> <type>boolean      </type> <description>true - Admin will allow the match, false - Admin will not allow the match, null - no decision yet</description></column>
      <column>   <name>coachAgree  </name> <type>boolean      </type> <description>true - away coach will allow the match, false - away coach will not allow the match, null - no decision yet</description></column>
      <reference><name>team1       </name> <table>team       </table> <description>The home team</description></reference>
      <reference><name>team2       </name> <table>team       </table> <description>The away team</description></reference>
      <reference><name>field       </name> <table>field      </table> <description>The field on which the match will be played</description></reference>
      <row><col>2020-03-08</col><col>1</col><col>22</col><col>0</col><col>0</col><col>1</col><col>2</col><col>1</col></row>
      <row><col>2020-04-18</col><col>1</col><col>13</col><col>0</col><col>0</col><col>1</col><col>3</col><col>1</col></row>
      <row><col>2020-04-22</col><col>1</col><col>13</col><col>0</col><col>0</col><col>1</col><col>3</col><col>2</col></row>
      <row><col>2020-04-25</col><col>1</col><col>13</col><col>0</col><col>0</col><col>1</col><col>3</col><col>2</col></row>
    </table>

    <table>
      <name>auth</name> <hide/>
      <column>   <name>state     </name> <type>varchar(16) </type>  <description>The unique state number which connects a random number on the browser to a unique github userid on the server </description></column>
      <column>   <name>token     </name> <type>varchar(64) </type>  <description>The token from github                                            </description></column>
      <column>   <name>scope     </name> <type>varchar(255)</type>  <description>The scope from github                                            </description></column>
      <column>   <name>tokenType </name> <type>varchar(16) </type>  <description>The type of token we got from github                             </description></column>
      <column>   <name>avatar_url</name> <type>varchar(255)</type>  <description>https://avatars1.githubusercontent.com/u/7548378?v=4             </description></column>
      <column>   <name>bio       </name> <type>varchar(255)</type>  <description>Biography                                                                 </description></column>
      <column>   <name>blog      </name> <type>varchar(255)</type>  <description>http://www.appaapps.com                                          </description></column>
      <column>   <name>company   </name> <type>varchar(255)</type>  <description>Appa Apps Ltd Inc                                                </description></column>
      <column>   <name>created_at</name> <type>varchar(255)</type>  <description>2014-05-11T11:19:04Z                                             </description></column>
      <column>   <name>email     </name> <type>varchar(255)</type>  <description>philiprbrenan\@gmail.com                                         </description></column>
      <column>   <name>location  </name> <type>varchar(255)</type>  <description>Terra                                                            </description></column>
      <column>   <name>login     </name> <type>varchar(255)</type>  <description>philiprbrenan                                                    </description></column>
      <column>   <name>name      </name> <type>varchar(255)</type>  <description>philip r brenan                                                  </description></column>
    </table>
  </database>
  END


    my $dd = xmlToPerl($xml, $paths);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my %table  = map {$_->name => $_}                                    $dd->table->@*;
    my %column = map {$_->name => {map {$_->name => $_} $_->column->@*}} $dd->table->@*;

    ok $table{auth}->hide;
    ok $column{matches}{coachAgree}{type} eq q(boolean);
    is_deeply $column{field}{street},
      bless({description => "Street address of the field",
             name        => "street",
             type        => "varchar(255)",
            }, "database::table::column");

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::xmlToPerl

Documentation

Update documentation describing this module

Compression

Read and write files of compressed xml. These methods provide a compact, efficient way to store and retrieve parse trees to/from files.

writeCompressedFile($node, $file)

Write the parse tree starting at $node as compressed Xml to the specified $file. Use readCompressedFile to read the $file.

     Parameter  Description
  1  $node      Parse tree node
  2  $file      File to write to.

Example:

    my $a = Data::Edit::Xml::new(q(<a>).(q(<b>𝝱</b>)x1e3).q(</a>));


    my $file = $a->writeCompressedFile(q(zzz.xml.zip));                              # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    my $A = readCompressedFile($file);

    ok $a->equals($A);

readCompressedFile($file)

Read the specified $file containing compressed Xml and return the root node. Use writeCompressedFile to write the $file.

     Parameter  Description
  1  $file      File to read.

Example:

    my $a = Data::Edit::Xml::new(q(<a>).(q(<b>𝝱</b>)x1e3).q(</a>));

    my $file = $a->writeCompressedFile(q(zzz.xml.zip));


    my $A = readCompressedFile($file);                                               # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    ok $a->equals($A);

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::readCompressedFile

Autoload

Allow methods with constant parameters to be called as method_p1_p2...(variable parameters) whenever it is easier to type underscores than (qw()).

AUTOLOAD()

Allow methods with constant parameters to be called as method_p1_p2...(variable parameters) whenever it is easier to type underscores than (qw()).

Example:

   {my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>
      <c/>
    </b>
  </a>
  END

    my ($c, $b) = $a->byList;

    ok  $c->at_c_b_a;

    ok !$c->at_b;

    ok  -t $c->change_d_c_b eq q(d);

    ok !   $c->change_d_b;

  if (1)
   {my $a = Data::Edit::Xml::new(<<END);
  <a><b><c/><d/><e/><f/></b></a>
  END

    ok -t $a->first_b__first_c__next__next_e__next eq q(f);
    ok   !$a->first_b__first_c__next__next_f;
   }

Data::Edit::Xml Definition

Well known attributes useful in respect to Xml that conforms to the Dita standard.

Output fields

attributes

The attributes of the specified $node, see also: "Attributes". The frequently used attributes: class, id, href, outputclass can be accessed by an lvalue method method as in: $node->id = 'c1'.

audience

Attribute audience for a node as an lvalue method sub. Use audienceX() to return q() rather than undef.

class

Attribute class for a node as an lvalue method sub. Use classX() to return q() rather than undef.

conditions

Conditional strings attached to a node, see "Conditions".

content

Content of command: the nodes immediately below the specified $node in the order in which they appeared in the source text, see also "Contents".

data

A hash added to the node for use by the programmer during transformations. The data in this hash will not be printed by any of the printed methods and so can be used to add data to the parse tree that will not be seen in any output Xml produced from the parse tree.

depthProfileLast

The last known depth profile for this node as set by setDepthProfiles.

errorsFile

Error listing file. Use this parameter to explicitly set the name of the file that will be used to write any parse errors to. By default this file is named: zzzParseErrors/out.data.

forestNumbers

Index to node by forest number as set by numberForest.

guid

Attribute guid for a node as an lvalue method sub. Use guidX() to return q() rather than undef.

href

Attribute href for a node as an lvalue method sub. Use hrefX() to return q() rather than undef.

id

Attribute id for a node as an lvalue method sub. Use idX() to return q() rather than undef.

indexes

Indexes to sub commands by tag in the order in which they appeared in the source text.

input

Source of the parse if this is the parser root node. Use this parameter to specify some input either as a string or as a file name for the parser to convert into a parse tree.

inputFile

Source file of the parse if this is the parser root node. Use this parameter to explicitly set the file to be parsed.

inputString

Source string of the parse if this is the parser root node. Use this parameter to explicitly set the string to be parsed.

labels

The labels attached to a node to provide addressability from other nodes, see: "Labels".

lang

Attribute lang for a node as an lvalue method sub. Use langX() to return q() rather than undef.

lineNumbers

If true then save the line number.column number at which tag starts and ends on the xtrf attribute of each node.

Attribute navtitle for a node as an lvalue method sub. Use navtitleX() to return q() rather than undef.

number

Number of the specified $node, see findByNumber.

numbering

Last number used to number a node in this parse tree.

numbers

Nodes by number.

otherprops

Attribute otherprops for a node as an lvalue method sub. Use otherpropsX() to return q() rather than undef.

outputclass

Attribute outputclass for a node as an lvalue method sub. Use outputclassX() to return q() rather than undef.

parent

Parent node of the specified $node or undef if the parser root node. See also "Traversal" and "Navigation". Consider as read only.

parser

Parser details: the root node of a tree is the parser node for that tree. Consider as read only.

props

Attribute props for a node as an lvalue method sub. Use propsX() to return q() rather than undef.

representationLast

The last representation set for this node by one of: setRepresentationAsTagsAndText.

style

Attribute style for a node as an lvalue method sub. Use styleX() to return q() rather than undef.

tag

Tag name for the specified $node, see also "Traversal" and "Navigation". Consider as read only.

text

Text of the specified $node but only if it is a text node otherwise undef, i.e. the tag is cdata() <=> "isText" is true.

type

Attribute type for a node as an lvalue method sub. Use typeX() to return q() rather than undef.

xtrc

Attribute xtrc for a node as an lvalue method sub. Use classX() to return q() rather than undef.

xtrf

Attribute xtrf for a node as an lvalue method sub. Use classX() to return q() rather than undef.

Data::Edit::Xml::Example Definition

Description of a pcd method

Output fields

also

See also

before

Before file content minus root tag which will be added as <a>

code

Pcd code

doc

One line summary

method

Method

Data::Edit::Xml::Table::Statistics Definition

Statistics about a table

Output fields

colSpec

Number of colspec entries

colsAttribute

Column attribute

maxBody

Maximum number of entries in a body row regardless of padding rows

maxBodyMinusPadding

Maximum number of entries in a body row after an padding entries have been removed

maxHead

Maximum number of entries in a head row regardless of padding rows

maxHeadMinusPadding

Maximum number of entries in a head row after an padding entries have been removed

minBody

Maximum number of entries in a body row regardless of padding rows

minHead

Maximum number of entries in a head row regardless of padding rows

rows

Number of rows

Attributes

The following is a list of all the attributes in this package. A method coded with the same name in your package will over ride the method of the same name in this package and thus provide your value for the attribute in place of the default value supplied for this attribute by this package.

Replaceable Attribute List

DESTROY

DESTROY

TO avoid seeing it in AUTOLOAD

Private Methods

reduceParseErroMessage($e)

Reduce the parse failure message to the bare essentials.

     Parameter  Description
  1  $e         Error message

tree($parent, $parse)

Build a tree representation of the parsed Xml which can be easily traversed to look for things.

     Parameter  Description
  1  $parent    The parent node
  2  $parse     The remaining parse

addLineNumbers($string)

Add line numbers to the source

     Parameter  Description
  1  $string    Source string

disconnectLeafNode($node)

Remove a leaf node from the parse tree and make it into its own parse tree.

     Parameter  Description
  1  $node      Leaf node to disconnect.

reindexNode($node)

Index the children of a node so that we can access them by tag and number.

     Parameter  Description
  1  $node      Node to index.

indexNode($node)

Merge multiple text segments and set parent and parser after changes to a node

     Parameter  Description
  1  $node      Node to index.

normalizeWhiteSpace($string)

Normalize white space, remove comments DOCTYPE and Xml processors from a string

     Parameter  Description
  1  $string    String to normalize

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::normalizeWhiteSpace

prettyStringHtml2($node, $depth)

Return a string of html representing a node of a parse tree and all the nodes below it. Or use -p $node

     Parameter  Description
  1  $node      Start node
  2  $depth     Optional depth.

prettyStringEnd($node)

Return a readable string representing a node of a parse tree and all the nodes below it as a here document

     Parameter  Description
  1  $node      Start node

jsonString2($node)

Return a Json representation of a parse tree

     Parameter  Description
  1  $node      Start node of parse tree

jsonToXml2($node)

Convert a json string to an Xml parse tree

     Parameter  Description
  1  $node      Start node of parse tree

by2($node, $sub, @context)

Post-order traversal of a parse tree

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node
  3  @context   Accumulated context.

By22($node, $sub)

Post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. A reference to the current node is also made available via $_. This is equivalent to the x= operator.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call for each sub node

byX2($node, $sub, @context)

Post-order traversal of a parse tree or sub tree calling the specified sub within eval{} at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call
  3  @context   Accumulated context.

byX22($node, $sub, @context)

Post-order traversal of a parse tree or sub tree calling the specified sub within eval{} at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call
  3  @context   Accumulated context.

downX2($node, $sub, @context)

Pre-order traversal of a parse tree or sub tree calling the specified sub within eval{} at each node and returning the specified starting node. The sub is passed references to the current node and all of its ancestors. The value of the current node is also made available via $_.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call
  3  @context   Accumulated context.

downToDie2($node, $sub, @context)

Pre-order traversal of a parse tree calling the specified sub at each node as long as this sub does not die. The traversal of the current sub tree is halted and continue with the next sibling or parent if the called sub does die. The sub is passed references to the current node and all of its ancestors up to the node on which this sub was called. A reference to the current node is also made available via $_.

Returns the start node regardless of the outcome of calling sub.

     Parameter  Description
  1  $node      Starting node
  2  $sub       Sub to call
  3  @context   Accumulated context.

parseLineLocation($loc)

Parse a line location

     Parameter  Description
  1  $loc       Location

This is a static method and so should either be imported or invoked as:

  Data::Edit::Xml::parseLineLocation

atPositionMatch($tag, $match)

Confirm that a string matches a match expression.

     Parameter  Description
  1  $tag       Starting node
  2  $match     Ancestry.

numberNode($node)

Ensure that the specified $node has a number.

     Parameter  Description
  1  $node      Node

countTagNames2($node, $count)

Return a reference to a hash showing the number of instances of each tag on and below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $count     Count of tags so far.

countNonEmptyTags2($node, $count)

Count the instances of non empty tags on and below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $count     Count of tags so far.

countTexts2($node, $count)

Count the instances of non empty texts on and below the specified $node.

     Parameter  Description
  1  $node      Node
  2  $count     Texts so far

countWords($node)

Count instances of words in texts

     Parameter  Description
  1  $node      Node

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <a>
    <b>aaa bbb ccc</b>
    <c>AAA BBB CCC</c>
    <c>aaa AAA</c>
  </a>
  END


    my $t = $a->countWords;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply $t, { AAA => 2, aaa => 2, bbb => 1, BBB => 1, CCC => 1, ccc => 1 };

createRequiredCleanUp($node, @text)

Create a required clean up $node with the specified @text

     Parameter  Description
  1  $node      Node
  2  @text      Clean up messages

ditaMergeListsOnce($node)

Merge the specified $node with the preceding or following list or steps or substeps if possible and return the specified $node regardless.

     Parameter  Description
  1  $node      Node

ditaNumberOfColumnsInRow($row)

Return estimate of the number of columns in a row

     Parameter  Description
  1  $row       Row

ditaAddPadEntriesToTGroupRows($tgroup, $nEntries)

Adding padding entries to a tgroup to make sure every row has the same number of entries

     Parameter  Description
  1  $tgroup    TGroup node
  2  $nEntries  Number of entries

Example:

    my $a = Data::Edit::Xml::new(<<END);
  <table>
    <tgroup cols="1">
      <colspec/>
      <thead>
        <row>
          <entry>aaaa</entry>
        </row>
        <row>
          <entry>bbbb</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
        </row>
        <row>
          <entry>dddd</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    my $g = $a->go_tgroup;


    $g->ditaAddPadEntriesToTGroupRows(2);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 1,
    colSpec => 1,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

    $g->fixTGroup;

    ok -p $a eq <<END;
  <table>
    <tgroup cols="2">
      <colspec colname="c1" colnum="1" colwidth="1*"/>
      <colspec colname="c2" colnum="2" colwidth="1*"/>
      <thead>
        <row>
          <entry>aaaa</entry>
          <entry/>
        </row>
        <row>
          <entry>bbbb</entry>
          <entry/>
        </row>
      </thead>
      <tbody>
        <row>
          <entry>cccc</entry>
          <entry/>
        </row>
        <row>
          <entry>dddd</entry>
          <entry/>
        </row>
      </tbody>
    </tgroup>
  </table>
  END

    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 2,
    colSpec => 2,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,

  }, "Data::Edit::Xml::Table::Statistics");

    $a->fixTable;
    is_deeply $g->ditaTGroupStatistics,
  bless({
    colsAttribute => 2,
    colSpec => 2,
    maxBody => 2,
    maxBodyMinusPadding => 2,
    maxHead => 2,
    maxHeadMinusPadding => 2,
    minBody => 2,
    minHead => 2,
    rows    => 4,
  }, "Data::Edit::Xml::Table::Statistics");

topicTypeAndBody($type)

Topic type and corresponding body.

     Parameter  Description
  1  $type      Type from qw(bookmap concept reference task)

getSectionHeadingLevel($o)

Get the heading level from a section tag.

     Parameter  Description
  1  $o         Node

unwrapSingleParentsOfSection($tree)

Unwrap single parents of section: in word documents the header is often buried in a list to gain a section number - here we remove these unnecessary items

     Parameter  Description
  1  $tree      Parse tree

extendSectionToNextSection($tree)

Extend a section tag until it meets the next section tag

     Parameter  Description
  1  $tree      Parse tree

structureAdjacentSectionsByLevel($tree)

Structure adjacent sections by level

     Parameter  Description
  1  $tree      Parse tree

ditaUnderPNotConbody()

Return a hash of items that Dita permits under p but not directly under conbody

printAttributesReplacingIdsWithLabels($node)

Print the attributes of a node replacing the id with the labels.

     Parameter  Description
  1  $node      Node whose attributes are to be printed.

printAttributesExtendingIdsWithLabels($node)

Print the attributes of a node extending the id with the labels.

     Parameter  Description
  1  $node      Node whose attributes are to be printed.

checkParentage($x)

Check the parent pointers are correct in a parse tree.

     Parameter  Description
  1  $x         Parse tree.

checkParser($x)

Check that every node has a parser.

     Parameter  Description
  1  $x         Parse tree.

nn($s)

Replace new lines in a string with N to make testing easier.

     Parameter  Description
  1  $s         String.

extractDocumentationFlags($flags, $method)

Generate documentation for a method with a user flag.

     Parameter  Description
  1  $flags     Flags
  2  $method    Method name.

writeContentToGitHub($file, $content)

Upload the contents of a string to a file on github

     Parameter  Description
  1  $file      File on github
  2  $content   File contents

writeFileToGitHub($file, $localFile)

Upload the contents of the specified local file to a file on github

     Parameter   Description
  1  $file       File name on github
  2  $localFile  Local file name

processModuleDescription($d)

Process module description to write a description of editing Xml to GitHub

     Parameter  Description
  1  $d         Module description

Synonyms

ca is a synonym for contentAfter - Return a list of all the sibling nodes following the specified $node or an empty list if the specified $node is last or not in the optional @context.

cb is a synonym for contentBefore - Return a list of all the sibling nodes preceding the specified $node (in the normal sibling order) or an empty list if the specified $node is last or not in the optional @context.

cc is a synonym for change - Change the name of the specified $node, optionally confirming that the $node is in a specified context and return the $node.

ck is a synonym for change - Change the name of the specified $node, optionally confirming that the $node is in a specified context and return the $node.

cr is a synonym for countReport - Count tags, attributes, words below the specified node

cs is a synonym for ditaConvertConceptToSection - Convert a Dita concept to a $section .

ct is a synonym for ditaConvertConceptToTask - Convert a Dita concept to a task by representing ol as steps.

firstLeaf is a synonym for downWhileFirst - Move down from the specified $node as long as each lower node is a first node.

get is a synonym for getNodeAs - Return the specified $node unless it is possible to return the node saved with putNodeAs under the specified name and we are optionally in the specified @context.

h is a synonym for help - Get help for a node and the editor

lastLeaf is a synonym for downWhileLast - Move down from the specified $node as long as each lower node is a last node.

ma is a synonym for moveSelectionAfter - Move the current selection (if there is one) after the specified $node in the optional @context and return the specified $node on success else undef.

mb is a synonym for moveSelectionBefore - Move the current selection (if there is one) before the specified $node in the optional @context and return the specified $node on success else undef.

mf is a synonym for moveSelectionFirst - Move the current selection (if there is one) so that it is first under the specified $node in the optional @context and return the specified $node on success else undef.

ml is a synonym for moveSelectionLast - Move the current selection (if there is one) so that it is last under the specified $node in the optional @context and return the specified $node on success else undef.

mln is a synonym for mergeLikeNext - Merge a $node in an optional context with the next node if the two have the same tag by placing the next node first in the current $node and unwrapping the next node.

mlp is a synonym for mergeLikePrev - Merge a $node in an optional context with the previous node if the two have the same tag by placing the previous node first in the current $node and unwrapping the previous node.

mocln is a synonym for mergeOnlyChildLikeNext - Merge a $node if it is the only child of its parent with a preceding node of the same name that is also the only child of its parent and return the specified $node or undef if the request fails.

moclp is a synonym for mergeOnlyChildLikePrev - Merge a $node if it is the only child of its parent with a preceding node of the same name that is also the only child of its parent and return the specified $node or undef if the request fails.

oat is a synonym for overAllTags - Return the specified b<$node> if all of it's child nodes match the specified <@tags> else return undef.

oft is a synonym for overFirstTags - Return the specified b<$node> if the first of it's child nodes match the specified <@tags> else return undef.

olt is a synonym for overLastTags - Return the specified b<$node> if the last of it's child nodes match the specified <@tags> else return undef.

p is a synonym for parentage - Return a reference to an array of the nodes along the path from the root to the specified $Node inclusive.

put is a synonym for putNodeAs - Return the specified $node after saving it under the specified $name if we are in the optional @context.

r is a synonym for dupPutNext - Duplicate the specified $tree in the optional @context, place the new tree next after $tree and return the root of the new tree on success else undef.

rN is a synonym for dupPutNextN - Duplicate the specified $tree $N times in the optional @context, placing each copy after $tree and return the last new node created on success else undef.

rn is a synonym for reportNode - Print the parse tree starting at the specified $node identified by the specified $label if we are in the optional @context.

rna is a synonym for reportNodeAttributes - Print the attributes of the specified $node identified by the specified $label if we are in the optional @context.

rnc is a synonym for reportNodeContext - Print the context of the specified $node identified by the specified $label if we are in the optional @context.

sc is a synonym for ditaConvertSectionToConcept - Convert a Dita $section to a concept.

se is a synonym for setSelectionEnd - Set the selection to end at the specified $node in the optional @context and return the specified $node on success else undef.

sfs is a synonym for swapFirstSibling - Swap $node with its first sibling node and return $node.

sls is a synonym for swapLastSibling - Swap $node with its last sibling node and return $node.

sn is a synonym for swapNext - Swap $node with its following node if $$node matches the first element of the specified context and the next node matches the rest.

sp is a synonym for swapPrev - Swap $node with its preceding node if $$node matches the first element of the specified context and the previous node matches the rest.

spa is a synonym for splitParentAfter - Finish and restart the parent of the specified $node just after the specified $node and return the newly created parent node on success or undef on failure.

spb is a synonym for splitParentBefore - Finish and restart the parent of the specified $node just before the specified $node and return the newly created parent node on success or undef on failure.

ss is a synonym for setSelectionStart - Set the selection to start at the specified $node in the optional @context and return the specified $node on success else undef.

u is a synonym for unwrap - Unwrap the specified $node if in the optional @context by replacing the node with its contents.

wcw is a synonym for wrapContentWith - Wrap the content of the specified $node in a new node created from the specified $tag and %attributes: the specified $node then contains just the new node which, in turn, contains all the content of the specified $node.

ww is a synonym for wrapWithAll - Wrap this $node wrapped with the specified @tags and return the last wrapping node.

x is a synonym for cut - Cut out and return the specified $node so that it can be reinserted else where in the parse tree.

Index

1 above - Return the first node if the first node is above the second node optionally checking that the first node is in the specified context otherwise return undef

2 abovePath - Return the nodes along the path from the first node down to the second node when the first node is above the second node else return ().

3 addAttr - Check the specified $node for the specified %attributes and add any that are not already set.

4 addConditions - Given a $node add the specified @conditions and return the node.

5 addFirst - Add a new node first below the specified $node with the specified $tag unless a node with that tag already exists in that position.

6 addFirstAsText - Add a new text node first below the specified $node and return the new node unless a text node already exists there and starts with the same text in which case return the existing $node.

7 addLabels - Add the named labels to the specified $node and return the number of labels added.

8 addLast - Add a new node last below the specified $node with the specified $tag unless a node with that tag already exists in that position.

9 addLastAsText - Add a new text node last below the specified $node and return the new node unless a text node already exists there and ends with the same text in which case return the existing $node.

10 addLineNumbers - Add line numbers to the source

11 addNext - Add a new node next the specified $node and return the new node unless a node with that tag already exists in which case return the existing $node.

12 addNextAsText - Add a new text node after the specified $node and return the new node unless a text node already exists there and starts with the same text in which case return the existing $node.

13 addPrev - Add a new node before the specified $node with the specified $tag unless a node with that tag already exists in that position.

14 addPrevAsText - Add a new text node before the specified $node and return the new node unless a text node already exists there and ends with the same text in which case return the existing $node.

15 addSingleChild - Wrap the content of a specified $node in a new node with the specified $tag unless the content is already wrapped in a single child with the specified $tag.

16 addWrapWith - Wrap the specified $node with the specified tag if the node is not already wrapped with such a tag and return the new node unless a node with that tag already exists in which case return the existing $node.

17 adjacent - Return the first node if it is adjacent to the second node else undef.

18 adoptChild - Lift the specified $child node up until it is an immediate child of the specified $parent node by splitting any intervening nodes.

19 after - Return the first node if it occurs after the second node in the parse tree optionally checking that the first node is in the specified context or else undef if the node is above, below or before the target.

20 allConditions - Return the $node if it has all of the specified @conditions, else return undef

21 an - Return the next node if the specified $node has the tag specified by $current and the next node is in the specified @context.

22 ancestry - Return a list containing: (the specified $node, its parent, its parent's parent etc.

23 anyCondition - Return the $node if it has any of the specified @conditions, else return undef

24 ap - Return the previous node if the specified $node has the tag specified by $current and the previous node is in the specified @context.

25 apn - Return (previous node, next node) if the $previous and $current nodes have the specified tags and the next node is in the specified @context else return ().

26 approxLocation - Return the line number.

27 at - Confirm that the specified $node has the specified ancestry.

28 atOrBelow - Confirm that the node or one of its ancestors has the specified context as recognized by at and return the first node that matches the context or undef if none do.

29 atPositionMatch - Confirm that a string matches a match expression.

30 atStringContentMatches - Confirm that we are on a $node whose contents, represented as a string, matches the specified regular expression $re in the optional @context.

31 atText - Confirm that we are on a text node whose text value matches a regular expression in the optional @context.

32 atTop - Return the current node if it is the root == top of a parse tree else return undef.

33 attr - Return the value of an attribute of the current node as an lvalue method sub.

34 attrAt - Return the specified $node if it has the specified $attribute and the $node is in the optional @context else return undef.

35 attrCount - Return the number of attributes in the specified $node, optionally ignoring the specified names from the count.

36 attrs - Return the values of the specified attributes of the current node as a list

37 attrsNone - Check that the specified $node has no attributes.

38 attrValueAt - Return the specified $node if it has the specified $attribute with the specified $value and the $node is in the optional @context else return undef.

39 attrX - Return the value of the specified $attribute of the specified $node or q() if the $node does not have such an attribute.

40 AUTOLOAD - Allow methods with constant parameters to be called as method_p1_p2.

41 before - Return the first node if it occurs before the second node in the parse tree optionally checking that the first node is in the specified context or else undef if the node is above, below or before the target.

42 below - Return the first node if the first node is below the second node optionally checking that the first node is in the specified context otherwise return undef

43 belowPath - Return the nodes along the path from the first node up to the second node when the first node is below the second node else return ().

44 bitsNodeTextBlank - Return a bit string that shows if there are any non text nodes, text nodes or blank text nodes under a node.

45 breakIn - Concatenate the nodes following and preceding the start node, unwrapping nodes whose tag matches the start node and return the start node.

46 breakInBackwards - Concatenate the nodes preceding the start node, unwrapping nodes whose tag matches the start node and return the start node in the manner of breakIn.

47 breakInForwards - Concatenate the nodes following the start node, unwrapping nodes whose tag matches the start node and return the start node in the manner of breakIn.

48 breakOut - Lift child nodes with the specified tags under the specified parent node splitting the parent node into clones and return the cut out original node.

49 breakOutChild - Lift the specified $node up one level splitting its parent.

50 by - Post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting node.

51 by2 - Post-order traversal of a parse tree

52 By22 - Post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting node.

53 byList - Return a list of all the nodes at and below a specified $node in post-order or the empty list if the $node is not in the optional @context.

54 byReverse - Reverse post-order traversal of a parse tree or sub tree calling the specified sub at each node and returning the specified starting $node.

55 byReverseList - Return a list of all the nodes at and below a specified $node in reverse preorder or the empty list if the specified $node is not in the optional @context.

56 byReverseX - Reverse post-order traversal of a parse tree or sub tree below the specified $node calling the specified sub within eval{} at each node and returning the specified starting $node.

57 byX - Post-order traversal of a parse tree calling the specified sub at each node as long as this sub does not die.

58 byX2 - Post-order traversal of a parse tree or sub tree calling the specified sub within eval{} at each node and returning the specified starting node.

59 byX22 - Post-order traversal of a parse tree or sub tree calling the specified sub within eval{} at each node and returning the specified starting node.

60 c - Return an array of all the nodes with the specified tag below the specified $node.

61 cdata - The name of the tag to be used to represent text - this tag must not also be used as a command tag otherwise the parser will confess.

62 change - Change the name of the specified $node, optionally confirming that the $node is in a specified context and return the $node.

63 changeAttr - Rename attribute $old to $new in the specified $node with optional context @context unless attribute $new is already set and return the $node.

64 changeAttributeValue - Apply a sub to the value of an attribute of the specified $node.

65 changeAttrValue - Rename attribute $old to $new with new value $newValue on the specified $node in the optional @context unless attribute $new is already set or the value of the $old attribute is not $oldValue.

66 changeKids - Change the names of all the immediate children of the specified $node, if they match the optional @context, to the specified $tag and return the $node.

67 changeOrDeleteAttr - Rename attribute $old to $new in the specified $node in the optional @context unless attribute $new is already set in which case delete attribute $old.

68 changeOrDeleteAttrValue - Rename attribute $old to $new with new value $newValue on the specified $node in the optional @context unless attribute $new is already set or the value of the $old attribute is not $oldValue in which cases the $old attribute is deleted.

69 changeReasonCommentSelectionSpecification - Provide a specification to select change reason comments to be inserted as text into a parse tree.

70 changeText - Change the content of the specified text $node that matches a regular expression $rf presented as a string to a string $rt in the optional @context and return the specified $node else return undef.

71 changeTextToSpace - Change each instance of the content of the specified text $node that matches a regular expression $re to one space and return the specified $node else return undef.

72 checkAllPaths - Create a representation of all the paths permitted in a block of Xml.

73 checkParentage - Check the parent pointers are correct in a parse tree.

74 checkParser - Check that every node has a parser.

75 childOf - Returns the specified $child node if it is a child of the specified $parent node and the $child node is in the specified optional context.

76 clone - Return a clone of the entire parse tree which is created using the fast Storable::dclone method.

77 closestLocation - Return the nearest node with line number.

78 commonAdjacentAncestors - Given two nodes, find a pair of adjacent ancestral siblings if such a pair exists else return ().

79 commonAncestor - Find the most recent common ancestor of the specified nodes or undef if there is no common ancestor.

80 concatenate - Concatenate two successive nodes and return the $target node.

81 concatenateSiblings - Concatenate the nodes that precede and follow the specified $node in the optioonal @context as long as they have the same tag as the specified $node and return the specified $node.

82 condition - Return the $node if it has the specified $condition and is in the optional @context, else return undef

83 containsSingleText - Return the single text element below the specified $node else return undef.

84 contentAfter - Return a list of all the sibling nodes following the specified $node or an empty list if the specified $node is last or not in the optional @context.

85 contentAfterAsTags - Return a string containing the tags of all the sibling nodes following the specified $node separated by single spaces or the empty string if the node is empty or undef if the node does not match the optional context.

86 contentAfterAsTags2 - Return a string containing the tags of all the sibling nodes following the specified $node separated by two spaces with a single space preceding the first tag and a single space following the last tag or the empty string if the node is empty or undef if the node does not match the optional context.

87 contentAsTags - Return a string containing the tags of all the child nodes of the specified $node separated by single spaces or the empty string if the node is empty or undef if the node does not match the optional context.

88 contentAsTags2 - Return a string containing the tags of all the child nodes of the specified $node separated by two spaces with a single space preceding the first tag and a single space following the last tag or the empty string if the node is empty or undef if the node does not match the optional context.

89 contentBefore - Return a list of all the sibling nodes preceding the specified $node (in the normal sibling order) or an empty list if the specified $node is last or not in the optional @context.

90 contentBeforeAsTags - Return a string containing the tags of all the sibling nodes preceding the specified $node separated by single spaces or the empty string if the node is empty or undef if the node does not match the optional context.

91 contentBeforeAsTags2 - Return a string containing the tags of all the sibling nodes preceding the specified $node separated by two spaces with a single space preceding the first tag and a single space following the last tag or the empty string if the node is empty or undef if the node does not match the optional context.

92 contents - Return a list of all the nodes contained by the specified $node or an empty list if the node is empty or not in the optional @context.

93 context - Return a string containing the tag of the starting node and the tags of all its ancestors separated by single spaces.

94 copyAttrs - Copy all the attributes of the source node to the target node, or, just the named attributes if the optional list of attributes to copy is supplied, overwriting any existing attributes in the target node and return the source node.

95 copyAttrsFromParent - Copy all the attributes from the parent (if there is one) of the current $node to $node or just the named @attributes and return $node.

96 copyAttrsToParent - Copy all the attributes of the specified $node to its parent (if there is one) or just the named @attributes and return $node.

97 copyLabels - Copy all the labels from the source node to the target node and return the source node.

98 copyLabelsAndIdsInTree - Copy all the labels and ids in the source parse tree to the matching nodes in the target parse tree.

99 copyNewAttrs - Copy all the attributes of the source node to the target node, or, just the named attributes if the optional list of attributes to copy is supplied, without overwriting any existing attributes in the target node and return the source node.

100 count - Return the count of the number of instances of the specified tags under the specified $node, either by tag in array context or in total in scalar context.

101 countAttrNames - Return a reference to a hash showing the number of instances of