Iteratively using replace() on nodes gives unexpected results
Opened this issue · 3 comments
For example:
my @elements = $mydocument.root.nodes;
for @elements -> $element {
my $new-element = @new-elements.pop;
$mydocument.root.replace($element, $new-element);
}
seems to result in only the first and last $new-element ending up in the document. Sorry, I have not golfed this down further. I see a similar result with the replaceChild() syntax.
Also weird, when I look at the code for the other bug, I'll look into this one too.
Confirm dropping elements (...in 2024), not sure if my syntax is valid. Still, replacing nodes
with self drops 1/2 the elements:
~$ raku -MXML -e 'my $mydocument=open-xml($*ARGFILES.Str); \
my @elements = $mydocument.root.nodes; \
my @new-elements = $mydocument.root.nodes; \
@elements.say; say "\n____\n"; @new-elements.say; say "\n____\n"; \
for @elements -> $element { \
my $new-element = @new-elements.pop; \
$mydocument.root.replace($element, $new-element); \
}; .say for $mydocument;' ~/exemel_text.xml
[
<file>text1</file>
<file>text2</file>
<file>text3</file>
<file>text4</file>
]
____
[
<file>text1</file>
<file>text2</file>
<file>text3</file>
<file>text4</file>
]
____
<?xml version="1.0"?><root>
<file>text1</file>
<file>text2</file>
</root>
~$
Try reversing the @new-elements
replacement, now all 4 elements are replaced with blanks! (Also...weirdness with printing reversed array):
~$ raku -MXML -e 'my $mydocument=open-xml($*ARGFILES.Str); \
my @elements = $mydocument.root.nodes; \
my @new-elements = $mydocument.root.nodes.reverse; \
@elements.say; say "\n____\n"; @new-elements.say; say "\n____\n"; \
for @elements -> $element { \
my $new-element = @new-elements.pop; \
$mydocument.root.replace($element, $new-element); \
}; .say for $mydocument;' ~/exemel_text.xml
[
<file>text1</file>
<file>text2</file>
<file>text3</file>
<file>text4</file>
]
____
[
<file>text4</file>
<file>text3</file>
<file>text2</file>
<file>text1</file>
]
____
<?xml version="1.0"?><root>
</root>
~$
Different syntax but still errors: "No such method 'replace' for invocant of type 'Array'"
~$ raku -MXML -e 'my $mydocument=open-xml($*ARGFILES.Str); \
my @elements = $mydocument.root.nodes; \
my @new-elements = $mydocument.root.nodes.reverse; \
for @(@elements,@new-elements) -> $old,$new { \
$mydocument.root.nodes.replace($old, $new); \
}; .say for $mydocument;' ~/exemel_text.xml
No such method 'replace' for invocant of type 'Array'
in block <unit> at -e line 1
Maybe related to #69 ?
@supernovus
@bronco-creek
@jonathanstowe
@lizmat
@dwarring
@vrurg
Here's a working one-liner for replacing text
within user identified nodes
( restricted to top-level with :RECURSE(0)
and restricted to :TAG{"title"}
):
~$ raku -MXML -e 'my $xml = open-xml( $*ARGFILES.Str );
for $xml.elements( :RECURSE(0), :TAG{"title"} ) -> $E {
my $old = $E.contents[0];
my $new = XML::Text.new( text => $old.text.subst(/^old-text$/, "new-text" ) );
$E.replace( $old, $new );
}; .say for $xml;' file.xml
See: https://unix.stackexchange.com/a/771574/227738
Maybe add a warning to the XML docs page about trying to replace Elements without converting to XML::Element
first?