/// <summary> /// Return the fully merged sequence. /// </summary> public IList<XPathNavigator> MergeSequences() { XmlQueryNodeSequence newSequence; // Zero sequences to merge if (this.firstSequence == null) return XmlQueryNodeSequence.Empty; // One sequence to merge if (this.sequencesToMerge == null || this.sequencesToMerge.Count <= 1) return this.firstSequence; // Two or more sequences to merge newSequence = new XmlQueryNodeSequence(this.nodeCount); while (this.sequencesToMerge.Count != 1) { // Save last item in list in temp variable, and remove it from list IEnumerator<XPathNavigator> sequence = this.sequencesToMerge[this.sequencesToMerge.Count - 1]; this.sequencesToMerge.RemoveAt(this.sequencesToMerge.Count - 1); // Add current node to merged sequence newSequence.Add(sequence.Current); // Now move to the next node, and re-insert it into the list in reverse document order MoveAndInsertSequence(sequence); } // Add nodes in remaining sequence to end of list Debug.Assert(this.sequencesToMerge.Count == 1, "While loop should terminate when count == 1"); do { newSequence.Add(this.sequencesToMerge[0].Current); } while (this.sequencesToMerge[0].MoveNext()); return newSequence; }
/// <summary> /// Lookup a sequence of nodes that are indexed by the specified key value. /// Return a non-null empty sequence, if there are no nodes associated with the key. /// </summary> public XmlQueryNodeSequence Lookup(string key) { XmlQueryNodeSequence seq; if (!this.table.TryGetValue(key, out seq)) seq = new XmlQueryNodeSequence(); return seq; }
/// <summary> /// Lookup a sequence of nodes that are indexed by the specified key value. /// Return a non-null empty sequence, if there are no nodes associated with the key. /// </summary> public XmlQueryNodeSequence Lookup(string key) { XmlQueryNodeSequence seq = (XmlQueryNodeSequence) this.table[key]; if (seq == null) seq = new XmlQueryNodeSequence(); return seq; }
/// <summary> /// Add a node indexed by the specified key value. /// </summary> public void Add(string key, XPathNavigator navigator) { XmlQueryNodeSequence seq; if (!this.table.TryGetValue(key, out seq)) { // Create a new sequence and add it to the index seq = new XmlQueryNodeSequence(); seq.AddClone(navigator); this.table.Add(key, seq); } else { // The nodes are guaranteed to be added in document order with possible duplicates. // Add node to the existing sequence if it differs from the last one. Debug.Assert(navigator.ComparePosition(seq[seq.Count - 1]) >= 0, "Index nodes must be added in document order"); if (!navigator.IsSamePosition(seq[seq.Count - 1])) { seq.AddClone(navigator); } } }
/// <summary> /// Add a node indexed by the specified key value. /// </summary> public void Add(string key, XPathNavigator navigator) { XmlQueryNodeSequence seq = (XmlQueryNodeSequence) this.table[key]; if (seq == null) { // Create a new sequence and add it to the index seq = new XmlQueryNodeSequence(); seq.AddClone(navigator); this.table.Add(key, seq); } else { // Add node to existing sequence; don't add if it already there for (int i = 0; i < seq.Count; i++) { if (navigator.IsSamePosition(seq[i])) return; } seq.AddClone(navigator); } }
/// <summary> /// Get a comparer which guarantees a stable ordering among nodes, even those from different documents. /// </summary> public IList<XPathNavigator> DocOrderDistinct(IList<XPathNavigator> seq) { if (seq.Count <= 1) return seq; XmlQueryNodeSequence nodeSeq = (XmlQueryNodeSequence) seq; if (nodeSeq == null) nodeSeq = new XmlQueryNodeSequence(seq); return nodeSeq.DocOrderDistinct(this.docOrderCmp); }
/// <summary> /// Convert from the Clr type of "value" to the default Clr type that ILGen uses to represent the xml type, using /// the conversion rules of the xml type. /// </summary> internal object ChangeTypeXsltResult(XmlQueryType xmlType, object value) { if (value == null) throw new XslTransformException(Res.Xslt_ItemNull, string.Empty); switch (xmlType.TypeCode) { case XmlTypeCode.String: if (value.GetType() == XsltConvert.DateTimeType) value = XsltConvert.ToString((DateTime) value); break; case XmlTypeCode.Double: if (value.GetType() != XsltConvert.DoubleType) value = ((IConvertible) value).ToDouble(null); break; case XmlTypeCode.Node: if (!xmlType.IsSingleton) { XPathArrayIterator iter = value as XPathArrayIterator; // Special-case XPathArrayIterator in order to avoid copies if (iter != null && iter.AsList is XmlQueryNodeSequence) { value = iter.AsList as XmlQueryNodeSequence; } else { // Iterate over list and ensure it only contains nodes XmlQueryNodeSequence seq = new XmlQueryNodeSequence(); IList list = value as IList; if (list != null) { for (int i = 0; i < list.Count; i++) seq.Add(EnsureNavigator(list[i])); } else { foreach (object o in (IEnumerable) value) seq.Add(EnsureNavigator(o)); } value = seq; } // Always sort node-set by document order value = ((XmlQueryNodeSequence) value).DocOrderDistinct(this.docOrderCmp); } break; case XmlTypeCode.Item: { Type sourceType = value.GetType(); IXPathNavigable navigable; // If static type is item, then infer type based on dynamic value switch (XsltConvert.InferXsltType(sourceType).TypeCode) { case XmlTypeCode.Boolean: value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Boolean), value)); break; case XmlTypeCode.Double: value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Double), ((IConvertible) value).ToDouble(null))); break; case XmlTypeCode.String: if (sourceType == XsltConvert.DateTimeType) value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String), XsltConvert.ToString((DateTime) value))); else value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String), value)); break; case XmlTypeCode.Node: // Support XPathNavigator[] value = ChangeTypeXsltResult(XmlQueryTypeFactory.NodeS, value); break; case XmlTypeCode.Item: // Support XPathNodeIterator if (value is XPathNodeIterator) { value = ChangeTypeXsltResult(XmlQueryTypeFactory.NodeS, value); break; } // Support IXPathNavigable and XPathNavigator navigable = value as IXPathNavigable; if (navigable != null) { if (value is XPathNavigator) value = new XmlQueryNodeSequence((XPathNavigator) value); else value = new XmlQueryNodeSequence(navigable.CreateNavigator()); break; } throw new XslTransformException(Res.Xslt_UnsupportedClrType, sourceType.Name); } break; } } Debug.Assert(XmlILTypeHelper.GetStorageType(xmlType).IsAssignableFrom(value.GetType()), "Xml type " + xmlType + " is not represented in ILGen as " + value.GetType().Name); return value; }
public static IList<XPathNavigator> ItemsToNavigators(IList<XPathItem> listItems) { // Check to see if the navigator cache implements IList<XPathNavigator> IList<XPathNavigator> listNavs = listItems as IList<XPathNavigator>; if (listNavs != null) return listNavs; // Create XmlQueryNodeSequence, which does implement IList<XPathNavigator> XmlQueryNodeSequence seq = new XmlQueryNodeSequence(listItems.Count); for (int i = 0; i < listItems.Count; i++) seq.Add((XPathNavigator) listItems[i]); return seq; }
public static XmlQueryNodeSequence CreateOrReuse(XmlQueryNodeSequence seq, System.Xml.XPath.XPathNavigator navigator) { }
// Methods public static XmlQueryNodeSequence CreateOrReuse(XmlQueryNodeSequence seq) { }