2 new revisions:

Revision: 4b6ddd9a9b5c
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 06:44:07 2012
Log:      XMLlib: Enhanced `Remove Element(s)`....
http://code.google.com/p/robotframework/source/detail?r=4b6ddd9a9b5c

Revision: a8c284c4b0b1
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 06:56:29 2012
Log: XML lib: Better approach to handle invalid xpath with Remove Element(s...
http://code.google.com/p/robotframework/source/detail?r=a8c284c4b0b1

==============================================================================
Revision: 4b6ddd9a9b5c
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 06:44:07 2012
Log:      XMLlib: Enhanced `Remove Element(s)`.

Update issue 1234
Remove Element and Remove Elements now keep tail by default but can remove it if `remove_tail` is set. This is consistent with `Clear Element` and its `clear_tail` argument.
http://code.google.com/p/robotframework/source/detail?r=4b6ddd9a9b5c

Modified:
 /atest/robot/standard_libraries/xml/add_and_remove_elements.txt
 /atest/testdata/standard_libraries/xml/add_and_remove_elements.txt
 /src/robot/libraries/XML.py

=======================================
--- /atest/robot/standard_libraries/xml/add_and_remove_elements.txt Thu Oct 18 03:16:33 2012 +++ /atest/robot/standard_libraries/xml/add_and_remove_elements.txt Fri Oct 19 06:44:07 2012
@@ -25,6 +25,15 @@

 Remove Non-Direct Child Element
     Check Test Case    ${TESTNAME}
+
+Remove Element Keeps Tail By Default
+    Check Test Case    ${TESTNAME}
+
+Remove Element Can Be Configured To Remove Tail
+    Check Test Case    ${TESTNAME}
+
+Remove Element Keeps Tail When Parent or Sibling Contains No Text
+    Check Test Case    ${TESTNAME}

 Remove Element Fails If No Element Match
     Check Test Case    ${TESTNAME}
@@ -49,6 +58,12 @@

 Remove Elements Does Not Fail If No Element Match
     Check Test Case    ${TESTNAME}
+
+Remove Elements Keeps Tail By Default
+    Check Test Case    ${TESTNAME}
+
+Remove Elements Can Be Configured To Remove Tail
+    Check Test Case    ${TESTNAME}

 Remove Elements Requires Xpath
     Check Test Case    ${TESTNAME}
=======================================
--- /atest/testdata/standard_libraries/xml/add_and_remove_elements.txt Thu Oct 18 03:16:33 2012 +++ /atest/testdata/standard_libraries/xml/add_and_remove_elements.txt Fri Oct 19 06:44:07 2012
@@ -1,9 +1,11 @@
 *** Settings ***
-Resource        resource.txt
-Test Setup      Parse XML To Test Variable    ${SIMPLE}    \${XML}
+Resource          resource.txt
+Test Setup        Parse XML To Test Variable    ${SIMPLE}    \${XML}

 *** Variables ***
-${NEW}          <new attr="value"/>
+${NEW}            <new attr="value"/>
+${WITH TAIL}      <p>text with <b>bold</b>&amp;<i>italics</i>...</p>
+${WITH TAIL 2}    <p><b>bold</b><i>italics</i>...</p>

 *** Test Cases ***

@@ -43,6 +45,24 @@
     Remove Element    ${XML}    c2/gc
     Element Should Not Exist    ${XML}    c2/gc

+Remove Element Keeps Tail By Default
+    ${p} =    Remove Element    ${WITH TAIL}   i
+ Elements Should Be Equal ${p} <p>text with <b>bold</b>&amp;...</p>
+    Remove Element     ${p}    b
+    Elements Should Be Equal    ${p}    <p>text with &amp;...</p>
+
+Remove Element Keeps Tail When Parent or Sibling Contains No Text
+    ${p} =    Remove Element    ${WITH TAIL2}   i
+    Elements Should Be Equal    ${p}    <p><b>bold</b>...</p>
+    Remove Element    ${p}    b
+    Elements Should Be Equal    ${p}    <p>...</p>
+
+Remove Element Can Be Configured To Remove Tail
+    ${p} =    Remove Element    ${WITH TAIL}   i    remove_tail=True
+    Elements Should Be Equal    ${p}    <p>text with <b>bold</b>&amp;</p>
+    Remove Element     ${p}    b    remove_tail=YeS
+    Elements Should Be Equal    ${p}    <p>text with </p>
+
 Remove Element Fails If No Element Match
     [Documentation]    FAIL No element matching 'nonex' found.
     Remove Element    ${XML}    nonex
@@ -75,6 +95,16 @@
 Remove Elements Does Not Fail If No Element Match
     Remove Elements    ${XML}    nonex

+Remove Elements Keeps Tail By Default
+    ${p} =    Remove Elements    ${WITH TAIL}    xpath=*
+    Elements Should Be Equal    ${p}    <p>text with &amp;...</p>
+    ${p} =    Remove Elements    ${WITH TAIL 2}    xpath=*
+    Elements Should Be Equal    ${p}    <p>...</p>
+
+Remove Elements Can Be Configured To Remove Tail
+ ${p} = Remove Elements ${WITH TAIL} xpath=* remove_tail=please
+    Elements Should Be Equal    ${p}    <p>text with </p>
+
 Remove Elements Requires Xpath
     [Documentation]    FAIL No xpath given.
     Remove Elements    ${XML}
@@ -86,4 +116,3 @@
 Remove Elements Returns Root Element
     ${root} =    Remove Elements    ${SIMPLE}    xpath=c2
     Element Should Not Exist    ${root}    xpath=c2
-
=======================================
--- /src/robot/libraries/XML.py Fri Oct 19 04:51:03 2012
+++ /src/robot/libraries/XML.py Fri Oct 19 06:44:07 2012
@@ -994,7 +994,7 @@
             parent.insert(int(index), element)
         return source

-    def remove_element(self, source, xpath=''):
+    def remove_element(self, source, xpath='', remove_tail=False):
"""Removes the element matching `xpath` from the `source` structure.

         The element to remove from the `source` is specified with `xpath`
@@ -1002,21 +1002,27 @@
         `source` structure  is modified and also returned.

         The keyword fails if `xpath` does not match exactly one element.
- Use `Remove Elements` to remove all matched elements and `Add Element`
-        to add new ones.
+        Use `Remove Elements` to remove all matched elements.
+
+ Element's tail text is not removed by default, but that can be changed
+        by giving `remove_tail` a true value (e.g. any non-empty string).
+        See `Element attributes` section for more information about tail in
+        general.

         Examples using `${XML}` structure from `Example`:
         | Remove Element           | ${XML} | xpath=second |
         | Element Should Not Exist | ${XML} | xpath=second |
+ | Remove Element | ${XML} | xpath=html/p/b | remove_tail=yes | + | Element Text Should Be | ${XML} | Text with italics. | xpath=html/p | normalize_whitespace=yes |

         New in Robot Framework 2.7.5.
         """
         source = self.get_element(source)
         self._verify_removing_xpath(xpath)
-        self._remove_element(source, self.get_element(source, xpath))
+ self._remove_element(source, self.get_element(source, xpath), remove_tail)
         return source

-    def remove_elements(self, source, xpath=''):
+    def remove_elements(self, source, xpath='', remove_tail=False):
"""Removes all elements matching `xpath` from the `source` structure.

         The elements to remove from the `source` are specified with `xpath`
@@ -1026,6 +1032,9 @@
It is not a failure if `xpath` matches no elements. Use `Remove Element`
         to remove exactly one element and `Add Element` to add new ones.

+ Element's tail text is not removed by default, but that can be changed
+        by using `remove_tail` argument similarly as with `Remove Element`.
+
         Examples using `${XML}` structure from `Example`:
         | Remove Elements          | ${XML} | xpath=*/child      |
         | Element Should Not Exist | ${XML} | xpath=second/child |
@@ -1036,7 +1045,7 @@
         source = self.get_element(source)
         self._verify_removing_xpath(xpath)
         for element in self.get_elements(source, xpath):
-            self._remove_element(source, element)
+            self._remove_element(source, element, remove_tail)
         return source

     def _verify_removing_xpath(self, xpath):
@@ -1045,8 +1054,10 @@
         if xpath == '.':
             raise RuntimeError('Cannot remove root element.')

-    def _remove_element(self, root, element):
+    def _remove_element(self, root, element, remove_tail=False):
         parent = self._find_parent(root, element)
+        if element.tail and not remove_tail:
+            self._preserve_tail(element, parent)
         parent.remove(element)

     def _find_parent(self, root, element):
@@ -1055,6 +1066,14 @@
                 if child is element:
                     return parent

+    def _preserve_tail(self, element, parent):
+        index = list(parent).index(element)
+        if index == 0:
+            parent.text = (parent.text or '') + element.tail
+        else:
+            sibling = parent[index-1]
+            sibling.tail = (sibling.tail or '') + element.tail
+
     def clear_element(self, source, xpath='.', clear_tail=False):
         """Clears the contents of the specified element.


==============================================================================
Revision: a8c284c4b0b1
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 06:56:29 2012
Log: XML lib: Better approach to handle invalid xpath with Remove Element(s). Earlier handled xpath pointin to root element only if it was '.'.
http://code.google.com/p/robotframework/source/detail?r=a8c284c4b0b1

Modified:
 /src/robot/libraries/XML.py

=======================================
--- /src/robot/libraries/XML.py Fri Oct 19 06:44:07 2012
+++ /src/robot/libraries/XML.py Fri Oct 19 06:56:29 2012
@@ -462,6 +462,8 @@
         """
         if isinstance(source, basestring):
             source = self.parse_xml(source)
+        if not xpath:
+            raise RuntimeError('No xpath given.')
         if xpath == '.':  # ET < 1.3 does not support '.' alone.
             return [source]
         return source.findall(self._get_xpath(xpath))
@@ -1018,7 +1020,6 @@
         New in Robot Framework 2.7.5.
         """
         source = self.get_element(source)
-        self._verify_removing_xpath(xpath)
self._remove_element(source, self.get_element(source, xpath), remove_tail)
         return source

@@ -1043,17 +1044,10 @@
         New in Robot Framework 2.7.5.
         """
         source = self.get_element(source)
-        self._verify_removing_xpath(xpath)
         for element in self.get_elements(source, xpath):
             self._remove_element(source, element, remove_tail)
         return source

-    def _verify_removing_xpath(self, xpath):
-        if not xpath:
-            raise RuntimeError('No xpath given.')
-        if xpath == '.':
-            raise RuntimeError('Cannot remove root element.')
-
     def _remove_element(self, root, element, remove_tail=False):
         parent = self._find_parent(root, element)
         if element.tail and not remove_tail:
@@ -1065,6 +1059,7 @@
             for child in parent:
                 if child is element:
                     return parent
+        raise RuntimeError('Cannot remove root element.')

     def _preserve_tail(self, element, parent):
         index = list(parent).index(element)

Reply via email to