view release on metacpan or search on metacpan
---------
- 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
cp
=item Description:
Copies nodes matching the first B<xpath> to the destinations determined by the B<location> directive relative to the second B<xpath>. If more than one node matches the first B<xpath> than it is copied to the position relative to the corresponding nod...
The possible values for B<location> are: after, before, into, replace and cause copying the source nodes after, before, into (as the last child-node). the destination nodes. If replace B<location> is used, the source node is copied before the destina...
Some kind of type conversion is used when the types of the source and destination nodes are not equal. Thus, text, cdata, comment or processing instruction node data prepend, append or replace value of a destination attribute when copied before,after...
Attributes may be copied after, before or into some other attribute to append, prepend or replace the destination attribute value. They may also replace the destination attribute completely (both its name and value). To copy an attribute from one ele...
Elements may be copied into other elements (which results in appending the child-list of the destination element), or before, after or instead (replace) other nodes of any type except attributes.
Example: Replace living-thing elements in the document b with the coresponding creature elements of the document a.
xsh> copy a://creature replace b://living-thing
=item Description:
Use the B<expression> to create a new node of a given B<node-type> in the B<location> relative to the given B<xpath>.
For element nodes, the format of the B<expression> should look 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 the element name. No...
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.
The namespace B<expression> is only valid for elements and attributes and must evaluate to the namespace URI. In that case, the element or attribute name must have a prefix. The created node is associated with a given namespace.
Example: Append a new Hobbit element to the list of middle-earth creatures and name him Bilbo.
xsh> xadd element "<creature race='hobbit' manner='good'>" \
into /middle-earth/creatures
One of: B<after>, B<before>, B<into>, B<append>, B<prepend>, B<replace>.
NOTE: XSH 1.6 introduces two new values for location argument: B<append> and B<prepend> and slighlty changes behavior of B<after> and B<before>!
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 peace 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;
lib/XML/XSH/Completion.pm view on Meta::CPAN
our $match_save_doc=qr/${M}(save)(?:\s+|_|-)(?:(?:html|xml|xinclude|HTML|XML|XInclude|XINCLUDE)(?:\s+|_|-))?(?:(?:file|pipe|string|FILE|PIPE|STRING)\s+)?([a-zA-Z0-9_]*)$/;
our $match_save_filename=qr/${M}save(?:\s+|_|-)(?:(?:html|xml|xinclude|HTML|XML|XInclude|XINCLUDE)(?:\s+|_|-))?(?:(?:file|FILE)\s+)?[a-zA-Z0-9_]+\s+(\S*)$/;
our $match_filename=qr/${M}(?:\.|include)\s+(\S*)$/;
our $match_dir=qr/${M}(?:lcd)\s+(\S*)$/;
our $match_path_filename=qr/${M}(?:system\s|exec\s|\!)\s*\S*$|\s\|\s*\S*$/;
our $match_no_xpath=join '|',@XML::XSH::CompletionList::XSH_NOXPATH_COMMANDS;
our $match_no=qr/${M}(?:${match_no_xpath}|create\s+[a-zA-Z0-9_]*\s)\s*$/;
# PATH-completion: system, !, exec, |,
our @nodetypes = qw(element attribute attributes text cdata pi comment chunk entity_reference);
our @openflags1 = qw(HTML XML DOCBOOK);
our @openflags2 = qw(FILE PIPE STRING);
our @saveflags1 = qw(HTML XML XINCLUDE);
our @saveflags2 = qw(FILE PIPE STRING);
sub perl_complete {
my($word,$line,$pos) = @_;
my $endpos=$pos+length($word);
cpl('perl',$word,$line,$pos,$endpos);
}
lib/XML/XSH/Functions.pm view on Meta::CPAN
return 1;
}
# return XPath identifying a node within its parent's subtree
sub node_address {
my ($node)=@_;
my $name;
if ($_xml_module->is_element($node)) {
$name=$node->getName();
} 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 "@".$node->getName();
}
if ($node->parentNode) {
my @children;
lib/XML/XSH/Functions.pm view on Meta::CPAN
my ($node,$dest,$dest_doc,$where,$ns)=@_;
if ($_xml_module->is_document($node)) {
die "Error: Can't insert/copy/move document nodes!";
}
# 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);
return 'keep'; # as opposed to 'remove'
lib/XML/XSH/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/XSH/Functions.pm view on Meta::CPAN
if ($dest->hasChildNodes()) {
$dest->insertBefore($copy,$dest->firstChild());
} else {
$dest->appendChild($copy);
}
}
}
}
# 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/XSH/Functions.pm view on Meta::CPAN
push @nodes,$el;
} else {
print STDERR "invalid element $exp\n" unless "$QUIET";
}
} elsif ($type eq 'text') {
push @nodes,$doc->createTextNode($exp);
print STDERR "text=$exp\n" if $DEBUG;
} elsif ($type eq 'entity_reference') {
push @nodes,$doc->createEntityReference($exp);
print STDERR "entity_reference=$exp\n" if $DEBUG;
} elsif ($type eq 'cdata') {
push @nodes,$doc->createCDATASection($exp);
print STDERR "cdata=$exp\n" if $DEBUG;
} elsif ($type eq 'pi') {
my ($name,$data)=($exp=~/^\s*(?:\<\?)?(\S+)(?:\s+(.*?)(?:\?\>)?)?$/);
my $pi = $doc->createProcessingInstruction($name);
$pi->setData($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($exp);
print STDERR "comment=$exp\n" if $DEBUG;
lib/XML/XSH/Functions.pm view on Meta::CPAN
my ($id,$query,$doc)=_xpath($xp);
print STDERR "stripping whitespace in $query from $id=$_files{$id}\n\n" if "$DEBUG";
unless (ref($doc)) {
die "No such document '$id'!\n";
}
my $ql=find_nodes($xp);
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 "") {
$node->setData($data);
} else {
$node->unbindNode();
}
} elsif ($_xml_module->is_pi($node)) {
lib/XML/XSH/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 "") {
$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 "") {
$child->setData($data);
last;
} else {
$child->unbindNode();
}
} elsif ($_xml_module->is_element($child) or
$_xml_module->is_pi($child)) {
last;
lib/XML/XSH/Functions.pm view on Meta::CPAN
return unless get_local_node(_id());
$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 = get_local_node(_id())->lookupNamespaceURI($1);
lib/XML/XSH/Functions.pm view on Meta::CPAN
my $xm=$XML::XSH::Functions::_xml_module;
my @result;
foreach (@$ql) {
if ($xm->is_element($_)) {
push @result, 'element';
} elsif ($xm->is_attribute($_)) {
push @result, 'attribute';
} elsif ($xm->is_text($_)) {
push @result, 'text';
} elsif ($xm->is_cdata_section($_)) {
push @result, 'cdata';
} elsif ($xm->is_pi($_)) {
push @result, 'pi';
} elsif ($xm->is_entity_reference($_)) {
push @result, 'entity_reference';
} elsif ($xm->is_document($_)) {
push @result, 'document';
} elsif ($xm->is_document_fragment($_)) {
push @result, 'chunk';
} elsif ($xm->is_comment($_)) {
push @result, 'comment';
lib/XML/XSH/GDOMECompat.pm view on Meta::CPAN
my $type=$node->getNodeType();
my $attype=ATTRIBUTE_NODE();
return $type == $attype;
}
sub is_text {
my ($class,$node)=@_;
return $node->nodeType == TEXT_NODE;
}
sub is_text_or_cdata {
my ($class,$node)=@_;
return $node->nodeType == TEXT_NODE || $node->nodeType == CDATA_SECTION_NODE;
}
sub is_cdata_section {
my ($class,$node)=@_;
return $node->nodeType == CDATA_SECTION_NODE;
}
sub is_pi {
my ($class,$node)=@_;
return $node->nodeType == PROCESSING_INSTRUCTION_NODE;
}
lib/XML/XSH/Grammar.pm view on Meta::CPAN
/(params|parameters)\s/ param(s)
{ $item[2] }
param:
/[^=\s]+/ '=' expression
{ [$item[1],$item[3]] }
nodetype:
/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/
namespace:
/namespace\s/ expression
{ $item[2] }
loc:
/after\s/
{ "after" }
lib/XML/XSH/Help.pm view on Meta::CPAN
first <xpath> is copied to the location relative to the n'th
node matching the second <xpath>.
The possible values for <location> are: after, before, into,
replace and cause copying the source nodes after, before, into
(as the last child-node). the destination nodes. If replace
<location> is used, the source node is copied before the
destination node and the destination node is removed.
Some kind of type conversion is used when the types of the
source and destination nodes are not equal. Thus, text, cdata,
comment or processing instruction node data prepend, append or
replace value of a destination attribute when copied
before,after/into or instead (replace) an attribute, and vice
versa.
Attributes may be copied after, before or into some other
attribute to append, prepend or replace the destination
attribute value. They may also replace the destination
attribute completely (both its name and value). To copy an
attribute from one element to another, simply copy the
lib/XML/XSH/Help.pm view on Meta::CPAN
For element nodes, the format of the <expression> should look
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.
The namespace <expression> is only valid for elements and
attributes and must evaluate to the namespace URI. In that
lib/XML/XSH/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 peace 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/XSH/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/XSH/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/XSH/Parser.pm view on Meta::CPAN
$expectation->at($_[1]);
my $thisline;
tie $thisline, q{Parse::RecDescent::LineCounter}, \$text, $thisparser;
while (!$_matched && !$commit)
{
Parse::RecDescent::_trace(q{Trying production: [/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/]},
Parse::RecDescent::_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;
Parse::RecDescent::_trace(q{Trying terminal: [/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/]}, Parse::RecDescent::_tracefirst($text),
q{nodetype},
$tracelevel)
if defined $::RD_TRACE;
$lastsep = "";
$expectation->is(q{})->at($text);
unless ($text =~ s/\A($skip)/$lastsep=$1 and ""/e and $text =~ s/\A(?:element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference)//)
{
$expectation->failed();
Parse::RecDescent::_trace(q{<<Didn't match terminal>>},
Parse::RecDescent::_tracefirst($text))
if defined $::RD_TRACE;
last;
}
Parse::RecDescent::_trace(q{>>Matched terminal<< (return value: [}
. $& . q{])},
Parse::RecDescent::_tracefirst($text))
if defined $::RD_TRACE;
push @item, $item{__PATTERN1__}=$&;
Parse::RecDescent::_trace(q{>>Matched production: [/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/]<<},
Parse::RecDescent::_tracefirst($text),
q{nodetype},
$tracelevel)
if defined $::RD_TRACE;
$_matched = 1;
last;
}
unless ( $_matched || defined($return) || defined($score) )
lib/XML/XSH/Parser.pm view on Meta::CPAN
bless( {
'dircount' => 0,
'uncommit' => undef,
'patcount' => 1,
'strcount' => 0,
'number' => 0,
'error' => undef,
'line' => undef,
'items' => [
bless( {
'description' => '/element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference/',
'pattern' => 'element|attribute|attributes|text|cdata|pi|comment|chunk|entity_reference',
'mod' => '',
'hashname' => '__PATTERN1__',
'lookahead' => 0,
'ldelim' => '/',
'line' => '758',
'rdelim' => '/'
}, 'Parse::RecDescent::Token' )
],
'actcount' => 0
}, 'Parse::RecDescent::Production' )
src/xsh_grammar.xml view on Meta::CPAN
possible values for <xref linkend="loc"/> are: after,
before, into, replace and cause copying the source nodes
after, before, into (as the last child-node). the
destination nodes. If replace <xref linkend="loc"/> is
used, the source node is copied before the destination node
and the destination node is removed.
</para>
<para>
Some kind of type conversion is used when the types of the
source and destination nodes are not equal. Thus, text,
cdata, comment or processing instruction node data prepend,
append or replace value of a destination attribute when
copied before,after/into or instead (replace) an attribute,
and vice versa.
</para>
<para>
Attributes may be copied after, before or into some other
attribute to append, prepend or replace the destination
attribute value. They may also replace the destination
attribute completely (both its name and value).
To copy an attribute from one element to another,
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
</description>
<see-also>
<ruleref ref="insert_command"/>
<ruleref ref="move_command"/>
<ruleref ref="xmove_command"/>
</see-also>
</documentation>
</rule>
<rule id="nodetype" name="node-type" type="argtype">
<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
peace of XML.
</para>
<example>
<code>
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>'
<tab/>into //middle-earth/creatures;
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