Mercurial > pub > ImplabNet
diff Implab/Xml/JsonXmlReader.cs @ 229:5f7a3e1d32b9 v2
JsonXmlReader performance tuning
JsonScanner now operates strings and doesn't
parses number and literals.
Added SerializationHelpers to common serialize/deserialize operations
author | cin |
---|---|
date | Tue, 12 Sep 2017 19:07:42 +0300 |
parents | 6fa235c5a760 |
children | 302ca905c19e |
line wrap: on
line diff
--- a/Implab/Xml/JsonXmlReader.cs Tue Sep 12 01:19:12 2017 +0300 +++ b/Implab/Xml/JsonXmlReader.cs Tue Sep 12 19:07:42 2017 +0300 @@ -12,7 +12,7 @@ public bool skip; } - JsonParser m_parser; + JsonReader m_parser; JsonXmlReaderOptions m_options; JsonXmlReaderPosition m_position = JsonXmlReaderPosition.Initial; XmlNameTable m_nameTable; @@ -57,7 +57,7 @@ readonly string m_xsiNamespace; - public JsonXmlReader(JsonParser parser, JsonXmlReaderOptions options) { + public JsonXmlReader(JsonReader parser, JsonXmlReaderOptions options) { Safe.ArgumentNotNull(parser, nameof(parser)); m_parser = parser; @@ -77,7 +77,7 @@ // TODO validate m_jsonRootName, m_jsonArrayItemName - m_context = new XmlNameContext(null); + m_context = new XmlNameContext(null, 0); } public override int AttributeCount { @@ -314,22 +314,6 @@ case XmlNodeType.Element: // if the elemnt is empty the next element will be it's sibling return m_isEmpty; - - case XmlNodeType.Document: - case XmlNodeType.DocumentFragment: - case XmlNodeType.Entity: - case XmlNodeType.Text: - case XmlNodeType.CDATA: - case XmlNodeType.EntityReference: - case XmlNodeType.ProcessingInstruction: - case XmlNodeType.Comment: - case XmlNodeType.DocumentType: - case XmlNodeType.Notation: - case XmlNodeType.Whitespace: - case XmlNodeType.SignificantWhitespace: - case XmlNodeType.EndElement: - case XmlNodeType.EndEntity: - case XmlNodeType.XmlDeclaration: default: return true; } @@ -351,25 +335,29 @@ if (!IsSibling()) // the node is nested m_xmlDepth++; - m_context = new XmlNameContext(m_context); + var context = m_context; List<XmlSimpleAttribute> definedAttrs = null; // define new namespaces if (attrs != null) { foreach (var attr in attrs) { if (attr.QName.Name == "xmlns") { - m_context.DefinePrefix(ConvertValueToString(attr.Value), string.Empty); + if (context == m_context) + context = new XmlNameContext(m_context, m_xmlDepth); + context.DefinePrefix(ConvertValueToString(attr.Value), string.Empty); } else if (attr.Prefix == m_xmlnsPrefix) { - m_context.DefinePrefix(ConvertValueToString(attr.Value), attr.QName.Name); + if (context == m_context) + context = new XmlNameContext(m_context, m_xmlDepth); + context.DefinePrefix(ConvertValueToString(attr.Value), attr.QName.Name); } else { string attrPrefix; if (string.IsNullOrEmpty(attr.QName.Namespace)) continue; // auto-define prefixes - if (!m_context.LookupNamespacePrefix(attr.QName.Namespace, out attrPrefix) || string.IsNullOrEmpty(attrPrefix)) { + if (!context.LookupNamespacePrefix(attr.QName.Namespace, out attrPrefix) || string.IsNullOrEmpty(attrPrefix)) { // new namespace prefix added - attrPrefix = m_context.CreateNamespacePrefix(attr.QName.Namespace); + attrPrefix = context.CreateNamespacePrefix(attr.QName.Namespace); attr.Prefix = attrPrefix; if (definedAttrs == null) @@ -383,8 +371,10 @@ string p; // auto-define prefixes - if (!m_context.LookupNamespacePrefix(ns, out p)) { - p = m_context.CreateNamespacePrefix(ns); + if (!context.LookupNamespacePrefix(ns, out p)) { + if (context == m_context) + context = new XmlNameContext(m_context, m_xmlDepth); + p = context.CreateNamespacePrefix(ns); if (definedAttrs == null) definedAttrs = new List<XmlSimpleAttribute>(); @@ -397,6 +387,9 @@ attrs = definedAttrs.ToArray(); } + if (!empty) + m_context = context; + m_nodeType = XmlNodeType.Element; m_qName = new XmlQualifiedName(name, ns); m_prefix = p; @@ -406,14 +399,18 @@ } void EndElementNode(string name, string ns) { - if (IsSibling()) // closing the element which has children + if (IsSibling()) { + // closing the element which has children m_xmlDepth--; + } string p; if (!m_context.LookupNamespacePrefix(ns, out p)) throw new Exception($"Failed to lookup namespace '{ns}'"); - m_context = m_context.ParentContext; + if (m_context.Depth == m_xmlDepth) + m_context = m_context.ParentContext; + m_nodeType = XmlNodeType.EndElement; m_prefix = p; m_qName = new XmlQualifiedName(name, ns); @@ -456,7 +453,10 @@ break; case JsonXmlReaderPosition.ValueElement: if (!m_isEmpty) { - ValueNode(m_parser.ElementValue); + if (m_parser.ElementValue != null && !m_parser.ElementValue.Equals(string.Empty)) + ValueNode(m_parser.ElementValue); + else + goto case JsonXmlReaderPosition.ValueContent; m_position = JsonXmlReaderPosition.ValueContent; return true; } else { @@ -521,7 +521,7 @@ true ); else - ElementNode(m_jsonValueName, m_jsonNamespace, elementAttrs, m_parser.ElementValue as string == string.Empty); + ElementNode(m_jsonValueName, m_jsonNamespace, elementAttrs, m_parser.ElementValue.Equals(string.Empty)); break; default: throw new Exception($"Unexpected JSON element {m_parser.ElementType}: {m_parser.ElementName}");