Document and fix DOMSourceAnydata streaming 21/82321/2
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 29 May 2019 23:50:00 +0000 (01:50 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 30 May 2019 08:58:23 +0000 (10:58 +0200)
W3C DOM requires each document to have a single root element, and
we are using the anydata element as the container. This is required
because anydata (and anyxml) can hold a list, in which case we would
be faced with a document which has multiple root elements.

Document this fact and adjust streaming interfaces/handling to take
this into account.

JIRA: YANGTOOLS-993
Change-Id: Ifcc7777d60359c942b8f033307ab63295525ca1e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/DOMSourceAnydata.java
yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java
yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/StreamWriterFacade.java
yang/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/AbstractAnydataTest.java

index 04cb67e047fc942909b7dd19af3713d177d013da..8921da86aba4952529cdf5cffb2b38dd6e8da205 100644 (file)
@@ -27,6 +27,12 @@ import org.xml.sax.SAXException;
  * and can be changed at any time. Current implementation uses W3C DOM tree as the backing implementations, but others
  * are possible as well.
  *
+ * <p>
+ * Note that the DOMSource is expected to contain a top-level synthetic element, which acts as holder of namespace
+ * declarations coming from parsing context but is otherwise ignored. Parser-side of things is expected to reuse the
+ * {@code anydata} element name for this purpose. Writer-side of things is expected to skip this element except for
+ * its namespace declarations.
+ *
  * @author Robert Varga
  */
 @NonNullByDefault
index 609c4d541ba1a2bcf6a6963c4048830fc1fac2c5..ef6b5dd0edd0d389c538550e8ce083dc0e83b8ea 100644 (file)
@@ -87,8 +87,7 @@ final class SchemaAwareXMLStreamNormalizedNodeStreamWriter extends XMLStreamNorm
             if (parent == schema) {
                 endElement();
             }
-        } else if (schema instanceof ContainerSchemaNode || schema instanceof LeafSchemaNode
-                || schema instanceof AnyDataSchemaNode) {
+        } else if (schema instanceof ContainerSchemaNode || schema instanceof LeafSchemaNode) {
             endElement();
         }
     }
index 91e177e7da425bdbf741a9fa2dd40b1d30dda243..ac5cc6dbb1d431ef397e80c51d42ebaa8d5e8bb7 100644 (file)
@@ -218,23 +218,32 @@ final class StreamWriterFacade extends ValueWriter {
     void anydataWriteStreamReader(final XMLStreamReader reader) throws XMLStreamException {
         flushElement();
 
+        // Do not emit top-level element
+        int depth = 0;
         while (reader.hasNext()) {
             final int event = reader.next();
             switch (event) {
                 case XMLStreamConstants.START_ELEMENT:
-                    forwardStartElement(reader);
+                    if (depth != 0) {
+                        forwardStartElement(reader);
+                    } else {
+                        // anydata: forward namespaces only
+                        forwardNamespaces(reader);
+                    }
+                    ++depth;
                     break;
                 case XMLStreamConstants.END_ELEMENT:
-                    writer.writeEndElement();
+                    if (depth != 0) {
+                        writer.writeEndElement();
+                    }
+                    --depth;
                     break;
                 case XMLStreamConstants.CHARACTERS:
                     writer.writeCharacters(reader.getText());
                     break;
                 case XMLStreamConstants.COMMENT:
-                    writer.writeComment(reader.getText());
-                    break;
                 case XMLStreamConstants.SPACE:
-                    // Ignore insignificant whitespace
+                    // Ignore comments and insignificant whitespace
                     break;
                 case XMLStreamConstants.START_DOCUMENT:
                 case XMLStreamConstants.END_DOCUMENT:
@@ -273,6 +282,7 @@ final class StreamWriterFacade extends ValueWriter {
                         forwardStartElement(reader);
                     } else {
                         forwardNamespaces(reader);
+                        // anyxml, hence we need to forward attributes
                         forwardAttributes(reader);
                     }
                     ++depth;
index d5eef001561b8591327894f4d6476b2d507cbf98..a25616336832adab7dafc1a7906d4ea0d78ef3f6 100644 (file)
@@ -39,7 +39,9 @@ public abstract class AbstractAnydataTest {
     }
 
     static DOMSourceAnydata toDOMSource(final String str) throws IOException, SAXException {
-        return new DOMSourceAnydata(new DOMSource(readXmlToDocument(toInputStream(str)).getDocumentElement()));
+        return new DOMSourceAnydata(new DOMSource(
+            // DOMSource must have a single document element, which we are ignoring
+            readXmlToDocument(toInputStream("<IGNORED>" + str + "</IGNORED>")).getDocumentElement()));
     }
 
     static InputStream toInputStream(final String str) {