*/
package org.opendaylight.yangtools.yang.data.codec.xml;
-import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
import com.google.common.base.Strings;
* class referencing this class should be {@link XMLStreamNormalizedNodeStreamWriter}.
*/
final class StreamWriterFacade extends ValueWriter {
- /**
- * Simple namespace/localname holder, an alternative to QName.
- */
- private static final class NSName {
- private final String uri;
- private final String name;
-
- NSName(final String uri, final String name) {
- this.uri = requireNonNull(uri);
- this.name = requireNonNull(name);
- }
- }
-
private static final Logger LOG = LoggerFactory.getLogger(StreamWriterFacade.class);
private static final Set<String> BROKEN_NAMESPACES = ConcurrentHashMap.newKeySet();
private static final Set<String> LEGACY_ATTRIBUTES = ConcurrentHashMap.newKeySet();
// QName of an element we delayed emitting. This only happens if it is a naked element, without any attributes,
// namespace declarations or value.
- private Object openElement;
+ private QName openElement;
StreamWriterFacade(final XMLStreamWriter writer) {
this.writer = requireNonNull(writer);
private void flushElement() throws XMLStreamException {
if (openElement != null) {
- final String nsUri;
- final String localName;
- if (openElement instanceof QName) {
- final QName qname = (QName) openElement;
- nsUri = qname.getNamespace().toString();
- localName = qname.getLocalName();
- } else {
- verify(openElement instanceof NSName);
- final NSName nsname = (NSName) openElement;
- nsUri = nsname.uri;
- localName = nsname.name;
- }
- writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, localName, nsUri);
+ writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, openElement.getLocalName(),
+ openElement.getNamespace().toString());
openElement = null;
}
}
- void writeStartElement(final String namespace, final String localName) throws XMLStreamException {
- flushElement();
-
- final NamespaceContext context = writer.getNamespaceContext();
- final boolean reuseNamespace;
- if (context != null) {
- reuseNamespace = namespace.equals(context.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX));
- } else {
- reuseNamespace = XMLConstants.DEFAULT_NS_PREFIX.equals(writer.getPrefix(namespace));
- }
-
- if (!reuseNamespace) {
- writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, localName, namespace);
- writer.writeDefaultNamespace(namespace);
- } else {
- openElement = new NSName(namespace, localName);
- }
- }
-
void writeStartElement(final QName qname) throws XMLStreamException {
flushElement();
void writeEndElement() throws XMLStreamException {
if (openElement != null) {
- final String nsUri;
- final String localName;
- if (openElement instanceof QName) {
- final QName qname = (QName) openElement;
- nsUri = qname.getNamespace().toString();
- localName = qname.getLocalName();
- } else {
- verify(openElement instanceof NSName);
- final NSName nsname = (NSName) openElement;
- nsUri = nsname.uri;
- localName = nsname.name;
- }
-
- writer.writeEmptyElement(XMLConstants.DEFAULT_NS_PREFIX, localName, nsUri);
+ writer.writeEmptyElement(XMLConstants.DEFAULT_NS_PREFIX, openElement.getLocalName(),
+ openElement.getNamespace().toString());
openElement = null;
} else {
writer.writeEndElement();
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, skipping the default namespace
+ for (int i = 0; i < reader.getNamespaceCount(); ++i) {
+ final String prefix = reader.getNamespacePrefix(i);
+ if (!XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
+ writer.writeNamespace(prefix, reader.getNamespaceURI(i));
+ }
+ }
+ }
+ ++depth;
break;
case XMLStreamConstants.END_ELEMENT:
- writer.writeEndElement();
+ --depth;
+ if (depth != 0) {
+ writer.writeEndElement();
+ }
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:
forwardStartElement(reader);
} else {
forwardNamespaces(reader);
+ // anyxml, hence we need to forward attributes
forwardAttributes(reader);
}
++depth;
break;
case XMLStreamConstants.END_ELEMENT:
+ --depth;
if (depth != 0) {
writer.writeEndElement();
}
- --depth;
break;
case XMLStreamConstants.PROCESSING_INSTRUCTION:
forwardProcessingInstruction(reader);
}
void emitNormalizedAnydata(final NormalizedAnydata anydata) throws XMLStreamException {
+ flushElement();
try {
anydata.writeTo(XMLStreamNormalizedNodeStreamWriter.create(writer, anydata.getSchemaContext(),
new SingleChildDataNodeContainer(anydata.getContextNode())));