SF.net SVN: docutils:[9735 ] trunk/docutils

milde--- via Docutils-checkins <[email protected]>
Newsgroups gmane.text.docutils.cvs
Message-ID <[email protected]>
Revision: 9735
          http://sourceforge.net/p/docutils/code/9735
Author:   milde
Date:     2024-06-06 14:01:46 +0000 (Thu, 06 Jun 2024)
Log Message:
-----------
xml-parser: new optional argument `document` for `parse_node()`.

The default is a new "dummy" `nodes.document` instance.

* Passed to the auxiliary `element2node()` function.
* Fixes ``parse_node('<document></document>)`` (instantiating
  `nodes.document` requires additional arguments).
* Provides a "reporter" instance.
* Provides a configuration settings instance.

Use `parse_node()` to simplify `Parser.parse()`.

Modified Paths:
--------------
    trunk/docutils/docutils/parsers/docutils_xml.py
    trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py

Modified: trunk/docutils/docutils/parsers/docutils_xml.py
===================================================================
--- trunk/docutils/docutils/parsers/docutils_xml.py	2024-06-06 14:01:35 UTC (rev 9734)
+++ trunk/docutils/docutils/parsers/docutils_xml.py	2024-06-06 14:01:46 UTC (rev 9735)
@@ -21,7 +21,7 @@
 
 import xml.etree.ElementTree as ET
 
-from docutils import nodes, parsers
+from docutils import frontend, nodes, parsers, utils
 
 
 class Parser(parsers.Parser):
@@ -45,24 +45,22 @@
         """
         self.setup_parse(inputstring, document)
 
-        # get ElementTree
-        root = ET.fromstring(inputstring)
-        # convert ElementTree to Docutils Document Tree
-        if root.tag == 'document':
-            convert_attribs(document, root.attrib)
-            for element in root:
-                document.append(element2node(element))
-        else:
-            document.append(element2node(root))
+        node = parse_element(inputstring, document)
+        if not isinstance(node, nodes.document):
+            document.append(node)
 
         self.finish_parse()
 
 
-def parse_element(inputstring):
+def parse_element(inputstring, document=None):
     """
     Parse `inputstring` as "Docutils XML", return `nodes.Element` instance.
 
     :inputstring: XML source.
+    :document: `nodes.document` instance (default: a new dummy instance).
+               Provides settings and reporter.
+               Populated and returned, if the inputstring's root element
+               is <document>.
 
     Caution:
       The function does not detect invalid XML.
@@ -75,10 +73,10 @@
 
     Provisional.
     """
-    return element2node(ET.fromstring(inputstring))
+    return element2node(ET.fromstring(inputstring), document)
 
 
-def element2node(element):
+def element2node(element, document=None):
     """
     Convert an `etree` element and its children to Docutils doctree nodes.
 
@@ -86,12 +84,22 @@
 
     Internal.
     """
+    if document is None:
+        document = utils.new_document('xml input',
+                                      frontend.get_default_settings(Parser))
+
     # Get the corresponding `nodes.Element` instance:
     nodeclass = getattr(nodes, element.tag)
-    node = nodeclass()
+    if nodeclass == nodes.document:
+        node = document
+    else:
+        node = nodeclass()
 
     # Attributes: convert and add to `node.attributes`.
-    convert_attribs(node, element.attrib)
+    for key, value in element.items():
+        if key.startswith('{'):
+            continue  # skip duplicate attributes with namespace URL
+        node.attributes[key] = nodes.ATTRIBUTE_VALIDATORS[key](value)
 
     # Append text (wrapped in a `nodes.Text` instance)
     append_text(node, element.text)
@@ -98,7 +106,7 @@
 
     # Append children and their tailing text
     for child in element:
-        node.append(element2node(child))
+        node.append(element2node(child, document))
         # Text after a child node
         append_text(node, child.tail)
 
@@ -105,14 +113,6 @@
     return node
 
 
-def convert_attribs(node, a):
-    # Convert doctree element attribute values from string to their datatype,
-    for key, value in a.items():
-        if key.startswith('{'):
-            continue  # skip duplicate attributes with namespace URL
-        node.attributes[key] = nodes.ATTRIBUTE_VALIDATORS[key](value)
-
-
 def append_text(node, text):
     if not text:
         return

Modified: trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py
===================================================================
--- trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py	2024-06-06 14:01:35 UTC (rev 9734)
+++ trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py	2024-06-06 14:01:46 UTC (rev 9735)
@@ -195,8 +195,14 @@
     # 'suffix': CDATA (str) → test_enumtype
 
     def test_title(self):  # CDATA (str)
-        ...
-        # TODO: <document> does not work with parse_element()
+        xml = (r'<document ids="test-document" names="test\ document"'
+               r'          source="/tmp/foo.rst" title="Test Document" />')
+        expected = {'ids': ['test-document'],
+                    'names': ['test document'],
+                    'source': '/tmp/foo.rst',
+                    'title': 'Test Document'}
+        node = docutils_xml.parse_element(xml)
+        self.assertEqual(node.attributes, self.common_attributes | expected)
 
     # 'uri': CDATA (str)                → test_alt
     # 'width' measure (str)             → test_alt

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



_______________________________________________
Docutils-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/docutils-checkins
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.