/// <summary> /// Asynchronously reads data into the current /// <see cref="SearchResultStream"/>. /// </summary> /// <param name="reader"> /// The <see cref="XmlReader"/> from which to read. /// </param> /// <returns> /// A <see cref="Task"/> representing the operation. /// </returns> public async Task ReadXmlAsync(XmlReader reader) { var fieldNames = new List<string>(); this.FieldNames = new ReadOnlyCollection<string>(fieldNames); this.IsFinal = true; if (!await reader.MoveToDocumentElementAsync("results").ConfigureAwait(false)) { return; } string preview = reader.GetRequiredAttribute("preview"); this.IsFinal = !BooleanConverter.Instance.Convert(preview); if (!await reader.ReadAsync().ConfigureAwait(false)) { return; } reader.EnsureMarkup(XmlNodeType.Element, "meta"); await reader.ReadAsync().ConfigureAwait(false); reader.EnsureMarkup(XmlNodeType.Element, "fieldOrder"); if (!reader.IsEmptyElement) { await reader.ReadEachDescendantAsync("field", async (r) => { await r.ReadAsync().ConfigureAwait(false); var fieldName = await r.ReadContentAsStringAsync().ConfigureAwait(false); fieldNames.Add(fieldName); }).ConfigureAwait(false); await reader.ReadEndElementSequenceAsync("fieldOrder", "meta").ConfigureAwait(false); } if (reader.NodeType == XmlNodeType.Element && reader.Name == "messages") { //// Skip messages await reader.ReadEachDescendantAsync("msg", (r) => { return Task.FromResult(true); }).ConfigureAwait(false); reader.EnsureMarkup(XmlNodeType.EndElement, "messages"); await reader.ReadAsync().ConfigureAwait(false); } }
/// <summary> /// Asynchronously reads data into the current <see cref="SearchResult"/>. /// </summary> /// <param name="reader"> /// The <see cref="XmlReader"/> from which to read. /// </param> /// <returns> /// A <see cref="Task"/> representing the operation. /// </returns> public async Task ReadXmlAsync(XmlReader reader) { Contract.Requires<ArgumentNullException>(reader != null, "reader"); reader.MoveToElement(); reader.EnsureMarkup(XmlNodeType.Element, "result"); this.Object = new ExpandoObject(); var dictionary = (IDictionary<string, object>)this.Object; this.SegmentedRaw = null; await reader.ReadEachDescendantAsync("field", async (r) => { var key = r.GetRequiredAttribute("k"); var values = new List<string>(); var fieldDepth = r.Depth; while (await r.ReadAsync().ConfigureAwait(false)) { if (r.Depth == fieldDepth) { break; } Debug.Assert(r.Depth > fieldDepth, "This loop should have exited earlier."); r.EnsureMarkup(XmlNodeType.Element, "value", "v"); if (r.Name == "value") { if (await r.ReadToDescendantAsync("text").ConfigureAwait(false)) { values.Add(await r.ReadElementContentAsStringAsync().ConfigureAwait(false)); } } else if (r.Name == "v") { Debug.Assert(this.SegmentedRaw == null); Debug.Assert(key == "_raw"); string value = await r.ReadOuterXmlAsync().ConfigureAwait(false); this.SegmentedRaw = XElement.Parse(value); values.Add(this.SegmentedRaw.Value); } } switch (values.Count) { case 0: dictionary.Add(key, null); break; case 1: dictionary.Add(key, values[0]); break; default: dictionary.Add(key, new ReadOnlyCollection<string>(values)); break; } }).ConfigureAwait(false); }
/// <summary> /// Asynchronously reads data into the current <see cref="SearchResult"/>. /// </summary> /// <param name="reader"> /// The <see cref="XmlReader"/> from which to read. /// </param> /// <returns> /// A <see cref="Task"/> representing the operation. /// </returns> public async Task ReadXmlAsync(XmlReader reader) { Contract.Requires<ArgumentNullException>(reader != null, "reader"); reader.MoveToElement(); reader.EnsureMarkup(XmlNodeType.Element, "result"); this.Object = new ExpandoObject(); var dictionary = (IDictionary<string, object>)this.Object; this.tagsObject = new ExpandoObject(); var tagsDictionary = (IDictionary<string, object>)this.tagsObject; this.SegmentedRaw = null; await reader.ReadEachDescendantAsync("field", async (r) => { ImmutableSortedSet<string>.Builder tags = null; var key = r.GetRequiredAttribute("k"); var values = new List<object>(); var fieldDepth = r.Depth; while (await r.ReadAsync().ConfigureAwait(false)) { if (r.Depth == fieldDepth) { break; } Debug.Assert(r.Depth > fieldDepth, "This loop should have exited earlier."); r.EnsureMarkup(XmlNodeType.Element, "value", "v"); if (r.Name == "value") { string value = null; while (await r.ReadAsync().ConfigureAwait(false)) { if (r.NodeType == XmlNodeType.EndElement) { r.EnsureMarkup(XmlNodeType.EndElement, "value"); break; } r.EnsureMarkup(XmlNodeType.Element, "text", "tag"); var isEmptyElement = r.IsEmptyElement; var elementName = r.Name; string content; if (isEmptyElement) { content = string.Empty; } else { await r.ReadAsync().ConfigureAwait(false); content = r.Value; } if (elementName == "tag") { if (tags == null) { tags = ImmutableSortedSet.CreateBuilder<string>(); } tags.Add(content); } else { value = content; } if (!isEmptyElement) { await r.ReadAsync().ConfigureAwait(false); r.EnsureMarkup(XmlNodeType.EndElement, elementName); } } if (tags != null && tags.Count > 0) { values.Add(new TaggedFieldValue(value ?? string.Empty, tags.ToImmutable())); tags.Clear(); } else { values.Add(value ?? string.Empty); } } else { Debug.Assert(this.SegmentedRaw == null); Debug.Assert(key == "_raw"); string value = await r.ReadOuterXmlAsync().ConfigureAwait(false); this.SegmentedRaw = XElement.Parse(value); values.Add(this.SegmentedRaw.Value); } } if (key.StartsWith("tag::")) { var valueSet = ImmutableSortedSet.ToImmutableSortedSet<string>(values.Cast<string>()); tagsDictionary.Add(key.Substring("tag::".Length), valueSet); dictionary.Add(key, valueSet); } else { switch (values.Count) { case 0: dictionary.Add(key, string.Empty); break; case 1: dictionary.Add(key, values[0]); break; default: dictionary.Add(key, new ReadOnlyCollection<object>(values)); break; } } }).ConfigureAwait(false); }