XML-XSH2

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

---------

- work with multiple DOM trees at once

- XPATH navigation (filesystem-like) navigation within a DOM tree

- copy/move nodes within a DOM tree or between two DOM trees

- node deletion

- node creation (element, attribute, text, cdata, comment,
  well-balanced chunk)

- XPATH search and XML listing of nodes matched with XPATH

- XPATH-based conditional statements, while statement

- foreach statement allowing usage of relative XPATH expressions

- command output filtering with unix pipe, for example
  xsh> list //word | grep [A-Z] | less 

XSH2.pod  view on Meta::CPAN

B<xsh(string,....)> - evaluates given string(s) as XSH2 commands.

B<call(name)> - call a given XSH2 subroutine.

B<count(string)> - evaluates given string as an XPath expression and returns either literal value of the result (in case of boolean, string and float result type) or number of nodes in a returned node-set.

B<literal(stringE<verbar>object)> - if passed a string, evaluates it as a XSH2 expression and returns the literal value of the result; if passed an object, returns literal value of the object. For example, B<literal('$docE<sol>expression')> returns t...

B<serialize(stringE<verbar>object)> - if passed a string, it first evaluates the string as a XSH2 expression to obtain a node-list object. Then it serializes the object into XML. The resulting string is equal to the output of the XSH2 command B<ls> a...

B<type(stringE<verbar>object)> - if passed a string, it first evaluates the string as XSH2 expression to obtain a node-list object. It returns a list of strings representing the types of nodes in the node-list (ordered in the canonical document order...

B<nodelist(stringE<verbar>object,...)> - converts its arguments to objects if necessary and returns a node-list consisting of the objects.

B<xpath(string, node?)> - evaluates a given string as an XPath expression in the context of a given node and returns the result.

B<echo(string,...)> - prints given strings on XSH2 output. Note, that in the interactive mode, XSH2 redirects all output to a specific terminal file handle stored in the variable B<$OUT>. So, if you for example mean to pipe the result to a shell comm...

In the following examples we use Perl to populate the Middle-Earth with Hobbits whose names are read from a text file called B<hobbits.txt>, unless there are some Hobbits in Middle-Earth already.

Example: Use Perl to read text files

XSH2.pod  view on Meta::CPAN

xadd

=item Description:

Create new nodes of the B<node-type> given in the 1st argument of name specified in the 2nd argument and insert them to B<location>s relative to nodes in the node-list specified in the 4th argument.

For element nodes, the the 2nd argument B<expression> should evaluate to something like "E<lt>element-name att-name='attvalue' ...E<gt>". The B<E<lt>> and B<E<gt>> characters are optional. If no attributes are used, the expression may simply consist ...

Attribute nodes use the following syntax: "att-name='attvalue' [...]".

For the other types of nodes (text, cdata, comments) the expression should contain the node's literal content. Again, it is necessary to quote all whitespace and special characters as in any expression argument.

The B<location> argument should be one of: B<after>, B<before>, B<into>, B<replace>, B<append> or B<prepend>. See documentation of the B<location> argument type for more detail.

Optionally, for element and attribute nodes, a namespace may be specified with B<--namespace> or B<:n>. If used, the expression should evaluate to the desired namespace URI and the name of the element or attribute being inserted must have a prefix.

The command returns a node-list consisting of nodes it created.

Note, that instead of B<xinsert>, you can alternatively use one of B<xsh:new-attribute>, B<xsh:new-cdata>, B<xsh:new-chunk>, B<xsh:new-comment>, B<xsh:new-element>, B<xsh:new-element-ns>, B<xsh:new-pi>, and B<xsh:new-text> together with the command B...

Example: Give each chapter a provisional title element.

  xsh> my $new_titles := xinsert element "<title font-size=large underline=yes>" \
        into /book/chapter
  xsh> xinsert text "Change me!" into $new_titles;

Example: Same as above, using xcopy and xsh:new-... instead of xinsert

  xsh> my $new_titles := xcopy xsh:new-element("title","font-size","large","underline","yes") \

XSH2.pod  view on Meta::CPAN

=item B<location>

One of: B<after>, B<before>, B<into>, B<append>, B<prepend>, B<replace>.

This argument is required by all commands that insert nodes to a document in some way to a destination described by an XPath expression. The meaning of the values listed above is supposed be obvious in most cases, however the exact semantics for loca...

B<afterE<sol>before> place the node right afterE<sol>before the destination node, except for when the destination node is a document node or one of the source nodes is an attribute: If the destination node is a document node, the source node is attac...

B<appendE<sol>prepend> appendsE<sol>prepends the source node to the destination node. If the destination node can contain other nodes (i.e. it is an element or a document node) then the entire source node is attached to it. In case of other destinati...

B<into> can also be used to place the source node to the end of an element (in the same way as B<append>), to attach an attribute to an element, or, if the destination node is a text node, cdata section, processing-instruction, attribute or comment, ...

B<replace> replaces the entire destination node with the source node except for the case when the destination node is an attribute and the source node is not. In such a case only the value of the destination attribute is replaced with the textual con...

=item B<node-type>

One of: element, attribute, text, cdata, comment, chunk and (EXPERIMENTALLY!) entity_reference. A chunk is a character string which forms a well-balanced piece of XML.

Example:

  add element hobbit into //middle-earth/creatures;
  add attribute 'name="Bilbo"' into //middle-earth/creatures/hobbit[last()];
  add chunk '<hobbit name="Frodo">A small guy from <place>Shire</place>.</hobbit>' 
    into //middle-earth/creatures;

=item B<nodename>

XSH2.pod  view on Meta::CPAN

should in XSH2 be written as either of

  /foo/bar[ @baz = "bar" ]

avoiding any white-space outside the square brackets, or completely enclosed in brackets as in

  ( / foo / bar [ @baz = "bar" ] ).

XSH2 provides a number of powerful XPath extension functions, listed below and described in separate sections. XPath extension functions by default belong to XSH2 namespace B<http:E<sol>E<sol>xsh.sourceforge.netE<sol>xshE<sol>> with a namespace prefi...

XPath extension functions defined in XSH2: xsh:base-uri, xsh:context, xsh:current, xsh:doc, xsh:document, xsh:document-uri, xsh:documents, xsh:evaluate, xsh:filename, xsh:grep, xsh:id2, xsh:if, xsh:join, xsh:lc, xsh:lcfirst, xsh:lineno, xsh:lookup, x...

Example: Open a document and count all sections containing a subsection

  xsh $scratch/> $v := open mydocument1.xml;
  xsh $v/> $k := open mydocument2.xml;
  xsh $k/> count //section[subsection]; # searches k
  xsh $k/> count $v//section[subsection]; # searches v

=back

XSH2.pod  view on Meta::CPAN


node-set xsh:new-attribute(string NAME1,string
  VALUE1,[string NAME2, string VALUE2, ...])

=item Description:

Return a node-set consisting of newly created attribute nodes with given names and respective values.

=back

=head2 xsh:new-cdata

=over 4

=item Usage:

node-set xsh:new-cdata(string DATA)

=item Description:

Create a new cdata section node node filled with given B<DATA> and return a node-set containing the new node as its only member.

=back

=head2 xsh:new-chunk

=over 4

=item Usage:

node-set xsh:new-chunk(string XML)

lib/XML/XSH2/Completion.pm  view on Meta::CPAN

our $NAMECHAR = '[-_.[:alnum:]]';
our $NNAMECHAR = '[-:_.[:alnum:]]';
our $NAME = "$NAMECHAR*$NNAMECHAR*[_.[:alpha:]]";

our $WILDCARD = '\*(?!\*|$NAME|\)|\]|\.)';
our $OPER = qr/(?:[,=<>\+\|]|-(?!$NAME)|(?:vid|dom|dna|ro)(?=\s*\]|\s*\)|\s*[0-9]+(?!$NNAMECHAR)|\s+{$NAMECHAR}|\s+\*))/;


# PATH-completion: system, !, exec, |, 

our @nodetypes = qw(element attribute attributes text cdata pi comment chunk entity_reference);

sub complete_option {
  my ($l)=@_;
  if ($l=~/\s--encoding\s+$|\s:e\s+$/) {
  }
  if ($l=~/$M(\.|[a-zA-Z_][-a-zA-Z0-9_]*)$F\s+(:([[:alnum:]]?)|--([-_[:alnum:]]*))$/) {
    my ($cmd,$o,$p)=($1,$2,$3||$4);
    my $c = $XML::XSH2::Functions::COMMANDS{$cmd};
    $c = $XML::XSH2::Functions::COMMANDS{$c} if (defined($c) and !ref($c));
    if (defined($c) and defined($c->[3])) {

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

  my $opts = shift;
  init_XPATH_funcs($_xpc,shift);
  return 1;
}

# ===================== XPATH EXT FUNC ================

sub get_XPATH_extensions {
  qw( current doc filename grep id2 if join lc uc ucfirst lcfirst
  lineno evaluate map matches match max min new-attribute
  new-cdata new-chunk new-comment new-element new-element-ns new-pi
  new-text node-type parse path reverse same serialize split sprintf
  strmax strmin subst substr sum times var document documents lookup span context
  resolve-uri base-uri document-uri
  )
}

sub XPATH_doc {
  die "Wrong number of arguments for function xsh:doc(nodeset)!\n" if (@_!=1);
  my ($nodelist)=@_;
  die "1st argument must be a nodeset in xsh:doc(nodeset)!\n"

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

    if (@_!=1);
  my $text=literal_value(shift);
  my $doc = $_xpc->getContextNode;
  unless (ref($doc) and ref($doc = $doc->ownerDocument())) {
    die "No context document\n";
  }
  my $t=$doc->createComment($text);
  return XML::LibXML::NodeList->new($t);
}

sub XPATH_new_cdata {
  die "Wrong number of arguments for function xsh:new-cdata(string)!\n"
    if (@_!=1);
  my $name=literal_value(shift);
  my $doc = $_xpc->getContextNode;
  unless (ref($doc) and ref($doc = $doc->ownerDocument())) {
    die "No context document\n";
  }
  my $t=$doc->createCDATASection($name);
  return XML::LibXML::NodeList->new($t);
}

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

}

# return XPath identifying a node within its parent's subtree
sub node_address {
  my $node = shift || $_xpc->getContextNode();
  my $no_parent = shift;
  my $name;
  if ($_xml_module->is_element($node)) {
    $name=cannon_name($node);
  } elsif ($_xml_module->is_text($node) or
	   $_xml_module->is_cdata_section($node)) {
    $name="text()";
  } elsif ($_xml_module->is_comment($node)) {
    $name="comment()";
  } elsif ($_xml_module->is_pi($node)) {
    $name="processing-instruction()";
  } elsif ($_xml_module->is_attribute($node)) {
    return "@".cannon_name($node);
  }
  
  if (!$no_parent and $node->parentNode) {

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

  if ($_xml_module->is_document($node)) {
    die "Error: Can't insert/copy/move document nodes!\n";
  }
  if (!defined($dest_doc)) {
    $dest_doc = $_xml_module->owner_document($dest);
  }
  # destination: Attribute
  if ($_xml_module->is_attribute($dest)) {
    # source: Text, CDATA, Comment, Entity, Element
    if ($_xml_module->is_text($node)           ||
	$_xml_module->is_cdata_section($node)  ||
	$_xml_module->is_comment($node) ||
	$_xml_module->is_element($node) ||
	$_xml_module->is_pi($node)) {
      my $val = $_xml_module->is_element($node) ?
	$node->textContent() : $node->getData();
      if ($where eq 'replace' or $where eq 'into') {
	$val=~s/^\s+|\s+$//g;
	# xcopy will replace the value several times, which may not be intended
	set_attr_ns($dest->ownerElement(),$dest->namespaceURI(),$dest->getName(),$val);
	push @$rl,$dest->ownerElement()->getAttributeNodeNS($dest->namespaceURI(),$dest->getName()) if defined($rl);

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

      _err("Warning: Ignoring incompatible nodes in insert/copy/move operation:\n",
            ref($node)," $where ",ref($dest),"!");
      return 1;
    }
  }
  # destination: Document
  elsif ($_xml_module->is_document($dest)) {
    # source: Attribute, Text, CDATA
    if ($_xml_module->is_attribute($node) or
	$_xml_module->is_text($node) or
	$_xml_module->is_cdata_section($node)
       ) {
      _err("Warning: Ignoring incompatible nodes in insert/copy/move operation:\n",
            ref($node)," $where ",ref($dest),"!");
      return 1;
    } elsif ($_xml_module->is_element($node)) {
    # source: Element
      my $copy=node_copy($node,$ns,$dest_doc,$dest);
      my $destnode;
      my $newwhere;
      if ($where =~ /^(?:after|append|into)/) {

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

	  $dest->insertBefore($copy,$dest->firstChild());
	} else {
	  $dest->appendChild($copy);
	}
	push @$rl,_expand_fragment($copy) if defined($rl);
      }
    }
  }
  # destination: Text, CDATA, Comment, PI
  elsif ($_xml_module->is_text($dest)          ||
	 $_xml_module->is_cdata_section($dest) ||
	 $_xml_module->is_comment($dest)       ||
	 $_xml_module->is_pi($dest) ||
	 $_xml_module->is_entity_reference($dest)
	) {
    if ($where =~ /^(?:into|append|prepend)$/ and
	($_xml_module->is_entity_reference($dest) ||
	 $_xml_module->is_entity_reference($node))) {
      _err("Warning: Ignoring incompatible nodes in insert/copy/move operation:\n",
	   ref($node)," $where ",ref($dest),"!");
      return 1;

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

  }
  return $el;
}

# create nodes from their textual representation
sub create_nodes {
  my ($type,$str,$doc,$ns)=@_;
  my @nodes=();
  die "No document for create $type $str for.\n" unless ref($doc);
  die "Can't create $type from empty specification.\n"
    if ($str eq "" and $type !~ /text|cdata|comment/);
#  return undef unless ($str ne "" and ref($doc));
  if ($type eq 'chunk') {
    @nodes=map {$_->childNodes()}
      grep {ref($_)} ($_parser->parse_xml_chunk($str));
  } else {
    if ($type eq 'attribute') {
      foreach (create_attributes($str)) {
	my $at;
	if ($_->[0]=~/^([^:]+):/ and $1 ne 'xmlns') {
	  $ns = get_registered_ns($1) if $ns eq "";

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

	# __debug("ns: $ns\n".$el->toString());
      } else {
	print STDERR "invalid element $str\n" unless "$QUIET";
      }
    } elsif ($type eq 'text') {
      push @nodes,$doc->createTextNode($str);
      print STDERR "text=$str\n" if $DEBUG;
    } elsif ($type eq 'entity_reference') {
      push @nodes,$doc->createEntityReference($str);
      print STDERR "entity_reference=$str\n" if $DEBUG;
    } elsif ($type eq 'cdata') {
      push @nodes,$doc->createCDATASection($str);
      print STDERR "cdata=$str\n" if $DEBUG;
    } elsif ($type eq 'pi') {
      my ($name,$data)=($str=~/^\s*(?:\<\?)?(\S+)(?:\s+(.*?)(?:\?\>)?)?$/);
      $data = "" unless defined $data;
      my $pi = $doc->createPI($name,$data);
      print STDERR "pi=<?$name ... $data?>\n" if $DEBUG;
      push @nodes,$pi;
      #    print STDERR "cannot add PI yet\n" if $DEBUG;
    } elsif ($type eq 'comment') {
      push @nodes,$doc->createComment($str);
      print STDERR "comment=$str\n" if $DEBUG;

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

      $data=_ev_literal($exp)
    } else {
      my $pwd = pwd($node);
      if ($fix) {
	undef $fix;
      } else {
	if ($_xml_module->is_attribute($node)) {
	  $data=$node->value;
	} elsif ($_xml_module->is_element($node) or
		 $_xml_module->is_document($node) or
		 $_xml_module->is_text_or_cdata($node) or
		 $_xml_module->is_comment($node) or
		 $_xml_module->is_pi($node)) {
	  $data=$_xml_module->toStringUTF8($node,$opts->{noindent} ? 0 :$INDENT);
	} else {
	  die("Cannot edit ".ref($node)."\n");
	}
      }
      $data="<!-- XSH-COMMENT: $pwd ".
	($opts->{all} ? "($node_idx/$nodes) " : "")."-->\n"
	  .$data unless $opts->{'no-comment'};

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

  return $text;
}

# strip whitespace from given nodes
sub strip_ws {
  my ($opts,$exp)=@_;
  my $ql=_ev_nodelist($exp);
  foreach my $node (@$ql) {
    if ($_xml_module->is_text($node)
	or
	$_xml_module->is_cdata_section($node)
	or
	$_xml_module->is_comment($node)
       ) {
      my $data=_trim_ws($node->getData());
      if ($data ne "") {
	$data = "" unless defined $data;
	$node->setData($data);
      } else {
	$node->unbindNode();
      }

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

    } elsif ($_xml_module->is_attribute($node)) {
      $node->setValue(_trim_ws($node->getValue));
    } elsif ($_xml_module->is_element($node) or
	     $_xml_module->is_document($node)) {
      # traverse children, skip comments, strip text nodes
      # until first element or PI or text node containing
      # a non-ws character
      my $child=$node->firstChild();
      while ($child) {
	if ($_xml_module->is_text($child) or
	    $_xml_module->is_cdata_section($child)) {
	  my $data=_trim_ws($child->getData());
	  if ($data ne "") {
	    $data = "" unless defined $data;
	    $child->setData($data);
	    last;
	  } else {
	    $child->unbindNode();
	  }
	} elsif ($_xml_module->is_element($child) or
		 $_xml_module->is_pi($child)) {
	  last;
	}
	$child=$child->nextSibling();
      }
      # traverse children (upwards), skip comments, strip text nodes
      # until first element or PI or text node containing a non-ws
      # character
      my $child=$node->lastChild();
      while ($child) {
	if ($_xml_module->is_text($child) or
	    $_xml_module->is_cdata_section($child)) {
	  my $data=_trim_ws($child->getData());
	  if ($data ne "") {
	    $data = "" unless defined $data;
	    $child->setData($data);
	    last;
	  } else {
	    $child->unbindNode();
	  }
	} elsif ($_xml_module->is_element($child) or
		 $_xml_module->is_pi($child)) {

lib/XML/XSH2/Functions.pm  view on Meta::CPAN

  my ($code,$axis,$nodefilter,$filter)=@_;

  $axis =~ s/::$//;
  $axis=~s/-/_/g;

  $filter =~ s/^\[\s*((?:.|\n)*?)\s*\]$/$1/ if defined $filter;
  my $test;
  if ($nodefilter eq "comment()") {
    $test = q{ $_xml_module->is_comment($_[0]) }
  } if ($nodefilter eq "text()") {
    $test = q{ $_xml_module->is_text_or_cdata($_[0]) }
  } elsif ($nodefilter =~ /processing-instruction\((\s*['"]([^'"]+)['"]\s*)?\)$/) {
    $test = q{ $_xml_module->is_pi($_[0]) };
    $test .= qq{ && (\$_[0]->nodeName eq '$1') } if $1 ne "";
  } elsif ($nodefilter eq 'node()') {
    $test = '1 ';
  } elsif ($nodefilter =~ /^(?:([^:]+):)?(.+)$/) {
    $test = q{ $_xml_module->is_element($_[0]) };
    $test .= qq{ && (\$_[0]->getLocalName() eq '$2') } unless ($2 eq '*');
    if ($1 ne "") {
      my $ns = xsh_context_node()->lookupNamespaceURI($1);

lib/XML/XSH2/Functions.pm  view on Meta::CPAN


sub node_type {
  my ($node)=@_;
  return undef unless $node;
  if ($_xml_module->is_element($node)) {
    return 'element';
  } elsif ($_xml_module->is_attribute($node)) {
    return 'attribute';
  } elsif ($_xml_module->is_text($node)) {
    return 'text';
  } elsif ($_xml_module->is_cdata_section($node)) {
    return 'cdata';
  } elsif ($_xml_module->is_pi($node)) {
    return 'pi';
  } elsif ($_xml_module->is_entity_reference($node)) {
    return 'entity_reference';
  } elsif ($_xml_module->is_document($node)) {
    return 'document';
  } elsif ($_xml_module->is_document_fragment($node)) {
    return 'chunk';
  } elsif ($_xml_module->is_comment($node)) {
    return 'comment';

lib/XML/XSH2/Grammar.pm  view on Meta::CPAN

	  [$thisline,$thiscolumn,$thisoffset,$XML::XSH2::Functions::SCRIPT,'undefine',$item[3]];
	 }
  	

  param:
	    /[^=\s]+/ '=' exp
		{ [$item[1],$item[3]] }
  	

  nodetype:
	    /element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/

  loc:
	    /after\s/
		{ "after" }
  	
	  | /before\s/
		{ "before" }
  	
	  | /(in)?to\s/
		{ "into" }

lib/XML/XSH2/Help.pm  view on Meta::CPAN


    $variable, block, command, document, encoding, expression, filename,
    location, node-type, nodename, perl-code, subroutine, xpath

  XPath Extension Functions:

    xsh:base-uri, xsh:context, xsh:current, xsh:doc, xsh:document,
    xsh:document-uri, xsh:documents, xsh:evaluate, xsh:filename, xsh:grep,
    xsh:id2, xsh:if, xsh:join, xsh:lc, xsh:lcfirst, xsh:lineno, xsh:lookup,
    xsh:map, xsh:match, xsh:matches, xsh:max, xsh:min, xsh:new-attribute,
    xsh:new-cdata, xsh:new-chunk, xsh:new-comment, xsh:new-element,
    xsh:new-element-ns, xsh:new-pi, xsh:new-text, xsh:parse, xsh:path,
    xsh:resolve-uri, xsh:reverse, xsh:same, xsh:serialize, xsh:span,
    xsh:split, xsh:sprintf, xsh:strmax, xsh:strmin, xsh:subst, xsh:substr,
    xsh:sum, xsh:times, xsh:uc, xsh:ucfirst, xsh:var

END

$HELP{'command'}=[<<'END'];
command

lib/XML/XSH2/Help.pm  view on Meta::CPAN

	     to 'xsh'. A program may however call the [xpath-extensions]
	     command to map XSH2 XPath extension functions into the default
	     namespace, so that they may be used directly without any
	     prefix.

	     XPath extension functions defined in XSH2: xsh:base-uri,
	     xsh:context, xsh:current, xsh:doc, xsh:document,
	     xsh:document-uri, xsh:documents, xsh:evaluate, xsh:filename,
	     xsh:grep, xsh:id2, xsh:if, xsh:join, xsh:lc, xsh:lcfirst,
	     xsh:lineno, xsh:lookup, xsh:map, xsh:match, xsh:matches,
	     xsh:max, xsh:min, xsh:new-attribute, xsh:new-cdata,
	     xsh:new-chunk, xsh:new-comment, xsh:new-element,
	     xsh:new-element-ns, xsh:new-pi, xsh:new-text, xsh:parse,
	     xsh:path, xsh:resolve-uri, xsh:reverse, xsh:same,
	     xsh:serialize, xsh:span, xsh:split, xsh:sprintf, xsh:strmax,
	     xsh:strmin, xsh:subst, xsh:substr, xsh:sum, xsh:times, xsh:uc,
	     xsh:ucfirst, xsh:var

Example:     Open a document and count all sections containing a subsection

             xsh $scratch/> $v := open mydocument1.xml;

lib/XML/XSH2/Help.pm  view on Meta::CPAN

	     For element nodes, the the 2nd argument [expression] should
	     evaluate to something like "<element-name att-name='attvalue'
	     ...>". The '<' and '>' characters are optional. If no
	     attributes are used, the expression may simply consist the
	     element name. Note, that in the first case, the quotes are
	     required since the expression contains spaces.

	     Attribute nodes use the following syntax: "att-name='attvalue'
	     [...]".

	     For the other types of nodes (text, cdata, comments) the
	     expression should contain the node's literal content. Again,
	     it is necessary to quote all whitespace and special characters
	     as in any expression argument.

	     The [location] argument should be one of: 'after', 'before',
	     'into', 'replace', 'append' or 'prepend'. See documentation of
	     the [location] argument type for more detail.

	     Optionally, for element and attribute nodes, a namespace may
	     be specified with '--namespace' or ':n'. If used, the
	     expression should evaluate to the desired namespace URI and
	     the name of the element or attribute being inserted must have
	     a prefix.

	     The command returns a node-list consisting of nodes it
	     created.

	     Note, that instead of 'xinsert', you can alternatively use one
	     of [xsh:new-attribute], [xsh:new-cdata], [xsh:new-chunk],
	     [xsh:new-comment], [xsh:new-element], [xsh:new-element-ns],
	     [xsh:new-pi], and [xsh:new-text] together with the command
	     [xcopy].

Example:     Give each chapter a provisional title element.

             xsh> my $new_titles := xinsert element "<title font-size=large underline=yes>" \
                              into /book/chapter
             xsh> xinsert text "Change me!" into $new_titles;

lib/XML/XSH2/Help.pm  view on Meta::CPAN

see also:     insert move xmove

END

$HELP{'xadd'}=$HELP{'xinsert'};

$HELP{'node-type'}=[<<'END'];
Node-type argument type

description:
	     One of: element, attribute, text, cdata, comment, chunk and
	     (EXPERIMENTALLY!) entity_reference. A chunk is a character
	     string which forms a well-balanced piece of XML.

Example:
             add element hobbit into //middle-earth/creatures;
             add attribute 'name="Bilbo"' into //middle-earth/creatures/hobbit[last()];
             add chunk '<hobbit name="Frodo">A small guy from <place>Shire</place>.</hobbit>' 
               into //middle-earth/creatures;

END

lib/XML/XSH2/Help.pm  view on Meta::CPAN

	     'append/prepend' appends/prepends the source node to the
	     destination node. If the destination node can contain other
	     nodes (i.e. it is an element or a document node) then the
	     entire source node is attached to it. In case of other
	     destination node types, the textual content of the source node
	     is appended/prepended to the content of the destination node.

	     'into' can also be used to place the source node to the end of
	     an element (in the same way as 'append'), to attach an
	     attribute to an element, or, if the destination node is a text
	     node, cdata section, processing-instruction, attribute or
	     comment, to replace its textual content with the textual
	     content of the source node.

	     'replace' replaces the entire destination node with the source
	     node except for the case when the destination node is an
	     attribute and the source node is not. In such a case only the
	     value of the destination attribute is replaced with the
	     textual content of the source node. Note also that document
	     node can never be replaced.

lib/XML/XSH2/Help.pm  view on Meta::CPAN

usage:       node-set xsh:new-pi(string NAME, [string DATA])
             
description:
	     Create a new processing instruction node node with given
	     'NAME' and (optionally) given 'DATA' and return a node-set
	     containing the new node as its only member.

END


$HELP{'xsh:new-cdata'}=[<<'END'];
usage:       node-set xsh:new-cdata(string DATA)
             
description:
	     Create a new cdata section node node filled with given 'DATA'
	     and return a node-set containing the new node as its only
	     member.

END


$HELP{'xsh:new-chunk'}=[<<'END'];
usage:       node-set xsh:new-chunk(string XML)
             
description:

lib/XML/XSH2/Help.pm  view on Meta::CPAN

    'serialize(string|object)' - if passed a string, it first evaluates the
    string as a XSH2 expression to obtain a node-list object. Then it
    serializes the object into XML. The resulting string is equal to the
    output of the XSH2 command [ls] applied on the same expression or
    object expression only without indentation and folding.

    'type(string|object)' - if passed a string, it first evaluates the
    string as XSH2 expression to obtain a node-list object. It returns a
    list of strings representing the types of nodes in the node-list
    (ordered in the canonical document order). The returned type strings
    are: 'element', 'attribute', 'text', 'cdata', 'pi', 'entity_reference',
    'document', 'chunk', 'comment', 'namespace', 'unknown'.

    'nodelist(string|object,...)' - converts its arguments to objects if
    necessary and returns a node-list consisting of the objects.

    'xpath(string, node?)' - evaluates a given string as an XPath
    expression in the context of a given node and returns the result.

    'echo(string,...)' - prints given strings on XSH2 output. Note, that in
    the interactive mode, XSH2 redirects all output to a specific terminal

lib/XML/XSH2/Help.pm  view on Meta::CPAN

             'xsh:map' => undef,
             'xsh:new-element-ns' => undef,
             'xsh:sum' => undef,
             'process-xinclude' => 'load and insert XInclude sections',
             'do' => 'execute a given block of commands',
             'xinsert' => 'create nodes on all target locations',
             'xsh:documents' => undef,
             'register-xsh-namespace' => 'register a prefix for the XSH2 namespace',
             'apropos' => 'search the documentation',
             'verbose' => 'make XSH2 print many messages',
             'xsh:new-cdata' => undef,
             'xsh:parse' => undef,
             'filename' => 'specifying filenames',
             'unregister-namespace' => 'unregister namespace prefix',
             'throw' => 'throw an exception',
             'xsh:new-text' => undef,
             'nobackups' => 'turn off backup file creation',
             'parser-expands-entities' => 'turn on/off parser\'s tendency to expand entities',
             'set-enc' => 'set document\'s charset (encoding)',
             'while' => 'simple while loop',
             'try' => 'try/catch statement',

lib/XML/XSH2/LibXMLCompat.pm  view on Meta::CPAN

sub is_attribute {
  my ($class,$node)=@_;
  return $node->nodeType == XML::LibXML::XML_ATTRIBUTE_NODE();
}

sub is_text {
  my ($class,$node)=@_;
  return $node->nodeType == XML::LibXML::XML_TEXT_NODE();
}

sub is_text_or_cdata {
  my ($class,$node)=@_;
  return $node->nodeType == XML::LibXML::XML_TEXT_NODE() || $node->nodeType == XML::LibXML::XML_CDATA_SECTION_NODE();
}

sub is_cdata_section {
  my ($class,$node)=@_;
  return $node->nodeType == XML::LibXML::XML_CDATA_SECTION_NODE();
}


sub is_pi {
  my ($class,$node)=@_;
  return $node->nodeType == XML::LibXML::XML_PI_NODE();
}

lib/XML/XSH2/Parser.pm  view on Meta::CPAN

    my @item = ();
    my %item = ();
    my $repeating =  $_[2];
    my $_noactions = $_[3];
    my @arg =    defined $_[4] ? @{ &{$_[4]} } : ();
    my $_itempos = $_[5];
    my %arg =    ($#arg & 01) ? @arg : (@arg, undef);
    my $text;
    my $lastsep;
    my $current_match;
    my $expectation = new XML::XSH2::Parser::_Runtime::Expectation(q{/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/});
    $expectation->at($_[1]);
    
    my $thisoffset;
    tie $thisoffset, q{XML::XSH2::Parser::_Runtime::OffsetCounter}, \$text, $thisparser;
    
    my $thiscolumn;
    tie $thiscolumn, q{XML::XSH2::Parser::_Runtime::ColCounter}, \$text, $thisparser;
    
    my $thisline;
    tie $thisline, q{XML::XSH2::Parser::_Runtime::LineCounter}, \$text, $thisparser;

    

    while (!$_matched && !$commit)
    {
        
        XML::XSH2::Parser::_Runtime::_trace(q{Trying production: [/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/]},
                      XML::XSH2::Parser::_Runtime::_tracefirst($_[1]),
                      q{nodetype},
                      $tracelevel)
                        if defined $::RD_TRACE;
        my $thisprod = $thisrule->{"prods"}[0];
        $text = $_[1];
        my $_savetext;
        @item = (q{nodetype});
        %item = (__RULE__ => q{nodetype});
        my $repcount = 0;


        XML::XSH2::Parser::_Runtime::_trace(q{Trying terminal: [/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/]}, XML::XSH2::Parser::_Runtime::_tracefirst($text),
                      q{nodetype},
                      $tracelevel)
                        if defined $::RD_TRACE;
        undef $lastsep;
        $expectation->is(q{})->at($text);
        

        unless ($text =~ s/\A($skip)/$lastsep=$1 and ""/e and   $text =~ m/\A(?:element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference)/)
        {
            $text = $lastsep . $text if defined $lastsep;
            $expectation->failed();
            XML::XSH2::Parser::_Runtime::_trace(q{<<Didn't match terminal>>},
                          XML::XSH2::Parser::_Runtime::_tracefirst($text))
                    if defined $::RD_TRACE;

            last;
        }
        $current_match = substr($text, $-[0], $+[0] - $-[0]);
        substr($text,0,length($current_match),q{});
        XML::XSH2::Parser::_Runtime::_trace(q{>>Matched terminal<< (return value: [}
                        . $current_match . q{])},
                          XML::XSH2::Parser::_Runtime::_tracefirst($text))
                    if defined $::RD_TRACE;
        push @item, $item{__PATTERN1__}=$current_match;
        

        XML::XSH2::Parser::_Runtime::_trace(q{>>Matched production: [/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/]<<},
                      XML::XSH2::Parser::_Runtime::_tracefirst($text),
                      q{nodetype},
                      $tracelevel)
                        if defined $::RD_TRACE;



        $_matched = 1;
        last;
    }

lib/XML/XSH2/Parser.pm  view on Meta::CPAN

                                                     'line' => 402,
                                                     'name' => 'nodetype',
                                                     'opcount' => 0,
                                                     'prods' => [
                                                                  bless( {
                                                                           'actcount' => 0,
                                                                           'dircount' => 0,
                                                                           'error' => undef,
                                                                           'items' => [
                                                                                        bless( {
                                                                                                 'description' => '/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/',
                                                                                                 'hashname' => '__PATTERN1__',
                                                                                                 'ldelim' => '/',
                                                                                                 'line' => 403,
                                                                                                 'lookahead' => 0,
                                                                                                 'mod' => '',
                                                                                                 'pattern' => 'element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference',
                                                                                                 'rdelim' => '/'
                                                                                               }, 'XML::XSH2::Parser::_Runtime::Token' )
                                                                                      ],
                                                                           'line' => undef,
                                                                           'number' => 0,
                                                                           'patcount' => 1,
                                                                           'strcount' => 0,
                                                                           'uncommit' => undef
                                                                         }, 'XML::XSH2::Parser::_Runtime::Production' )
                                                                ],

src/xsh_grammar.xml  view on Meta::CPAN

	  <literal>type(string|object)</literal> - 
	  if passed a string, it first evaluates
	  the string as &XSH; expression to obtain a node-list object.
	  It returns a list of strings representing
	  the types of nodes in the node-list
	  (ordered in the canonical document order).
	  The returned type strings are: 
	  <literal>element</literal>,
	  <literal>attribute</literal>,
	  <literal>text</literal>,
	  <literal>cdata</literal>,
	  <literal>pi</literal>,
	  <literal>entity_reference</literal>,
	  <literal>document</literal>,
	  <literal>chunk</literal>,
	  <literal>comment</literal>,
	  <literal>namespace</literal>,
	  <literal>unknown</literal>.
	</para>
	<para>
	  <literal>nodelist(string|object,...)</literal> - 

src/xsh_grammar.xml  view on Meta::CPAN

	      characters are optional. If no attributes are used, the
	      expression may simply consist the element name. Note,
	      that in the first case, the quotes are required since
	      the expression contains spaces.
	  </para>
	  <para>
	    Attribute nodes use the following syntax:
	    "att-name='attvalue' [...]".
	  </para>
	  <para>
	    For the other types of nodes (text, cdata, comments) the
	    expression should contain the node's literal content. Again,
	    it is necessary to quote all whitespace and special
	    characters as in any expression argument.
	  </para>
	  <para>
	    The <xref linkend="loc"/> argument should be one of:
	    <literal>after</literal>, <literal>before</literal>,
	    <literal>into</literal>,
	    <literal>replace</literal>, <literal>append</literal>
	    or <literal>prepend</literal>. See documentation

src/xsh_grammar.xml  view on Meta::CPAN

	    the expression should evaluate to the desired namespace
	    URI and the name of the element or attribute being inserted 
	    <emphasis>must have a prefix</emphasis>.
	  </para>
	  <para>
	    The command returns a node-list consisting of nodes it created.
	  </para>
	  <para>
	    Note, that instead of <literal>xinsert</literal>, you can alternatively use 
	    one of <xref linkend="new_attribute_function"/>,
	    <xref linkend="new_cdata_function"/>,
	    <xref linkend="new_chunk_function"/>,
	    <xref linkend="new_comment_function"/>,
	    <xref linkend="new_element_function"/>,
	    <xref linkend="new_element_ns_function"/>,
	    <xref linkend="new_pi_function"/>, and
	    <xref linkend="new_text_function"/>
	    together with the command <xref linkend="xcopy_command"/>.
	  </para>
	  <example>
	    <title>Give each chapter a provisional title element.</title>

src/xsh_grammar.xml  view on Meta::CPAN

	</description>
	<see-also>
	  <ruleref ref="insert_command" arguments=""/>
	  <ruleref ref="move_command" arguments=""/>
	  <ruleref ref="xmove_command" arguments=""/>
	</see-also>
      </documentation>
    </rule>
    <rule id="nodetype" name="node-type" type="argtype" inline="no">
      <production>
	<regexp>element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference</regexp>
      </production>
      <documentation sections="Argtypes Manipulation">
	<title>Node-type argument type</title>
	<shortdesc>node type specification (such as element, attribute, etc.)</shortdesc>
	<description>
	  <para>
	    One of: element, attribute, text, cdata, comment, chunk
	    and (EXPERIMENTALLY!) entity_reference.  A
	    chunk is a character string which forms a well-balanced
	    piece of XML.
	  </para>
	  <example>
	    <code>add element hobbit into //middle-earth/creatures;
	      add attribute 'name="Bilbo"' into //middle-earth/creatures/hobbit[last()];
	      add chunk '&lt;hobbit name="Frodo"&gt;A small guy from &lt;place&gt;Shire&lt;/place&gt;.&lt;/hobbit&gt;' 
	      <tab count="1"/>into //middle-earth/creatures;
	    </code>

src/xsh_grammar.xml  view on Meta::CPAN

	    document node) then the entire source node is attached to
	    it. In case of other destination node types, the textual
	    content of the source node is appended/prepended to the
	    content of the destination node.
	  </para>
	  <para>
	    <literal>into</literal> can also be used to place
	    the source node to the end of an element (in the same way
	    as <literal>append</literal>), to attach an attribute
	    to an element, or, if the destination node is a text node,
	    cdata section, processing-instruction, attribute or comment,
	    to replace its textual content with the textual content of 
	    the source node.
	  </para>
	  <para>
	    <literal>replace</literal> replaces the entire destination
	    node with the source node except for the case when the
	    destination node is an attribute and the source node is
	    not. In such a case only the value of the destination
	    attribute is replaced with the textual content of the
	    source node. Note also that document node can never be

src/xsh_grammar.xml  view on Meta::CPAN

	<description>
	  <para>
	    Create a new processing instruction node node with given
	    <literal>NAME</literal> and (optionally) given
	    <literal>DATA</literal> and return a node-set containing
	    the new node as its only member.
	  </para>
	</description>
      </documentation>
    </rule>
    <rule id="new_cdata_function" type="function" name="xsh:new-cdata" inline="no">
      <documentation>
	<usage>node-set xsh:new-cdata(string DATA)</usage>
	<description>
	  <para>
	    Create a new cdata section node node filled with
	    given <literal>DATA</literal> and return a node-set
	    containing the new node as its only member.
	  </para>
	</description>
      </documentation>
    </rule>
    <rule id="new_chunk_function" type="function" name="xsh:new-chunk" inline="no">
      <documentation>
	<usage>node-set xsh:new-chunk(string XML)</usage>
	<description>

t/08more_functions.t  view on Meta::CPAN

call x_assert 'new-element("foo","bar","baz","bag","dag")/self::foo[@bar="baz" and @bag="dag"]';

call x_assert 'new-element-ns("f:foo","gee","bar","baz","bag","dag")/self::*[name()="f:foo" and local-name()="foo" and namespace-uri()="gee" and @bar="baz" and @bag="dag"]';

call x_assert 'new-text("some text")/self::text()="some text"';

call x_assert 'new-comment("some text")/self::comment()="some text"';

call x_assert 'new-pi("name","value")/self::processing-instruction()[name()="name"]="value"';

call x_assert 'new-cdata("some text")/self::text()="some text"';

call x_assert 'serialize(new-cdata("some text"))="<![CDATA[some text]]>"';

EOF

  plan tests => 4+@xsh_test;
}
END { ok(0) unless $loaded; }
use XML::XSH2 qw/&xsh &xsh_init &set_quiet &xsh_set_output/;
$loaded=1;
ok(1);



( run in 0.293 second using v1.01-cache-2.11-cpan-ec4f86ec37b )