/// <summary>
        /// Creates a new XPathNavigator using the same source but positioned at a new root.
        /// </summary>
        /// <returns>A new XPathNavigator using the same source and positioned at a new root.</returns>
        /// <remarks>The new root can be above this navigator's root.</remarks>
        public XPathNavigator CloneWithNewRoot(int id, int maxDepth = int.MaxValue)
        {
            DebugEnter("CloneWithNewRoot");

            State state = null;

            if (id <= 0)
            {
                state = new State(_source.Root, null, null, 0, StatePosition.Root);
            }
            else
            {
                var content = SourceGet(id);
                if (content != null)
                {
                    state = new State(content, null, null, 0, StatePosition.Root);
                }
            }

            NavigableNavigator clone = null;

            if (state != null)
            {
                clone = new NavigableNavigator(this, state, maxDepth);
                DebugCreate(clone);
                DebugReturn("[XPathNavigator]");
            }
            else
            {
                DebugReturn("[null]");
            }

            return(clone);
        }
        public void NavigableXmlValues()
        {
            var source = new TestSource6();
            var nav = new NavigableNavigator(source);

            NavigatorValues(nav, false);
        }
        /// <summary>
        /// Creates a new XPathNavigator using the same source but positioned at a new root.
        /// </summary>
        /// <returns>A new XPathNavigator using the same source and positioned at a new root.</returns>
        /// <remarks>The new root can be above this navigator's root.</remarks>
        public XPathNavigator CloneWithNewRoot(string id)
        {
            DebugEnter("CloneWithNewRoot");

            int   contentId;
            State state = null;

            if (id != null && id.Trim() == "-1")
            {
                state = new State(_source.Root, null, null, 0, StatePosition.Root);
            }
            else if (int.TryParse(id, out contentId))
            {
                var content = _source.Get(contentId);
                if (content != null)
                {
                    state = new State(content, null, null, 0, StatePosition.Root);
                }
            }

            NavigableNavigator clone = null;

            if (state != null)
            {
                clone = new NavigableNavigator(_source, _nameTable, state);
                DebugCreate(clone);
                DebugReturn("[XPathNavigator]");
            }
            else
            {
                DebugReturn("[null]");
            }

            return(clone);
        }
        /// <summary>
        /// Creates a new XPathNavigator positioned at the same node as this XPathNavigator.
        /// </summary>
        /// <returns>A new XPathNavigator positioned at the same node as this XPathNavigator.</returns>
        public override XPathNavigator Clone()
        {
            DebugEnter("Clone");
            var nav = new NavigableNavigator(this);

            DebugCreate(nav);
            DebugReturn("[XPathNavigator]");
            return(nav);
        }
        /// <summary>
        /// Creates a new XPathNavigator positioned at the same node as this XPathNavigator.
        /// </summary>
        /// <returns>A new XPathNavigator positioned at the same node as this XPathNavigator.</returns>
        public override XPathNavigator Clone()
        {
            DebugEnter("Clone");
            var nav = new NavigableNavigator(_source, _nameTable, _state.Clone());

            DebugCreate(nav);
            DebugReturn("[XPathNavigator]");
            return(nav);
        }
        ///// <summary>
        ///// Initializes a new instance of the <see cref="NavigableNavigator"/> class with a content source, a name table and a state.
        ///// </summary>
        ///// <param name="source">The content source.</param>
        ///// <param name="nameTable">The name table.</param>
        ///// <param name="state">The state.</param>
        ///// <param name="maxDepth">The maximum depth.</param>
        ///// <remarks>Privately used for cloning a navigator.</remarks>
        //private NavigableNavigator(INavigableSource source, XmlNameTable nameTable, State state, int maxDepth)
        //    : this(source, rootId: 0, maxDepth: maxDepth)
        //{
        //    _nameTable = nameTable;
        //    _state = state;
        //}

        /// <summary>
        /// Initializes a new instance of the <see cref="NavigableNavigator"/> class as a clone.
        /// </summary>
        /// <param name="orig">The cloned navigator.</param>
        /// <param name="state">The clone state.</param>
        /// <param name="maxDepth">The clone maximum depth.</param>
        /// <remarks>Privately used for cloning a navigator.</remarks>
        private NavigableNavigator(NavigableNavigator orig, State state = null, int maxDepth = -1)
            : this(orig._source, rootId : 0, maxDepth : orig._maxDepth)
        {
            _nameTable = orig._nameTable;

            _state = state ?? orig._state.Clone();
            if (state != null && maxDepth < 0)
            {
                throw new ArgumentException("Both state and maxDepth are required.");
            }
            _maxDepth = maxDepth < 0 ? orig._maxDepth : maxDepth;

            _contents = orig._contents;
        }
        public void NewNavigatorIsAtRoot()
        {
            const string xml = @"<root><item1 /><item2 /></root>";
            var doc = XmlHelper.CreateXPathDocument(xml);
            var nav = doc.CreateNavigator();

            Assert.AreEqual(XPathNodeType.Root, nav.NodeType);
            Assert.AreEqual(string.Empty, nav.Name);

            var source = new TestSource5();
            nav = new NavigableNavigator(source);

            Assert.AreEqual(XPathNodeType.Root, nav.NodeType);
            Assert.AreEqual(string.Empty, nav.Name);
        }
        public void MixedWithNoValue()
        {
            var source = new TestSource4();
            var nav = new NavigableNavigator(source);

            var doc = XmlHelper.CreateXPathDocument(@"<root id=""-1"">
                        <type1 id=""1""><prop1><data value=""value""/></prop1><prop2>dang</prop2></type1>
                        <type1 id=""2""><prop1 /><prop2></prop2></type1>
                        <type1 id=""3""><prop1 /><prop2 /></type1>
                    </root>");
            var docNav = doc.CreateNavigator();

            docNav.MoveToRoot();
            Assert.IsTrue(docNav.MoveToFirstChild());
            Assert.AreEqual("root", docNav.Name);
            Assert.IsTrue(docNav.MoveToFirstChild());
            Assert.AreEqual("type1", docNav.Name);
            Assert.IsTrue(docNav.MoveToNext());
            Assert.AreEqual("type1", docNav.Name);
            Assert.IsTrue(docNav.MoveToNext());
            Assert.AreEqual("type1", docNav.Name);
            Assert.IsFalse(docNav.MoveToNext());

            docNav.MoveToRoot();
            var docOuter = docNav.OuterXml;

            nav.MoveToRoot();
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual("root", nav.Name);
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual("type1", nav.Name);
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual("type1", nav.Name);
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual("type1", nav.Name);
            Assert.IsFalse(nav.MoveToNext());

            nav.MoveToRoot();
            var outer = nav.OuterXml;

            Assert.AreEqual(docOuter, outer);
        }
        public void XmlNodeList()
        {
            var source = new TestSource1();
            var nav = new NavigableNavigator(source);

            var iterator = nav.Select("/*");

            // but, that requires that the underlying navigator implements IHasXmlNode
            // so it is possible to obtain nodes from the navigator - not possible yet
            var nodes = XmlNodeListFactory.CreateNodeList(iterator);

            Assert.AreEqual(nodes.Count, 1);
            var node = nodes[0];

            Assert.AreEqual(3, node.Attributes.Count);
            Assert.AreEqual("1", node.Attributes["id"].Value);
            Assert.AreEqual("1:p1", node.Attributes["prop1"].Value);
            Assert.AreEqual("1:p2", node.Attributes["prop2"].Value);
            Assert.AreEqual(1, node.ChildNodes.Count);
            Assert.AreEqual("prop3", node.FirstChild.Name);
            Assert.AreEqual("1:p3", node.FirstChild.Value);
        }
        public void QueryWithVariables()
        {
            var source = new TestSource1();
            var nav = new NavigableNavigator(source);

            var iterator = nav.Select("//* [@prop1=$var]", new XPathVariable("var", "1:p1"));
            Assert.AreEqual(1, iterator.Count);
            iterator.MoveNext();
            Assert.AreEqual("type1", iterator.Current.Name);
        }
        public void QueryMixedWithVariables()
        {
            var source = new TestSource2();
            var nav = new NavigableNavigator(source);

            var iterator = nav.Select("//item2 [@xx=$var]", new XPathVariable("var", "33"));
            Assert.AreEqual(1, iterator.Count);
            iterator.MoveNext();
            Assert.AreEqual("item2", iterator.Current.Name);
        }
        public void Query()
        {
            var source = new TestSource1();
            var nav = new NavigableNavigator(source);

            var iterator = nav.Select("//type1");
            Assert.AreEqual(1, iterator.Count);
            iterator.MoveNext();
            Assert.AreEqual("type1", iterator.Current.Name);

            iterator = nav.Select("//* [@prop1='1:p1']");
            Assert.AreEqual(1, iterator.Count);
            iterator.MoveNext();
            Assert.AreEqual("type1", iterator.Current.Name);
        }
        public void QueryMixed()
        {
            var source = new TestSource2();
            var nav = new NavigableNavigator(source);

            var doc = XmlHelper.CreateXPathDocument("<data><item1>poo</item1><item2 xx=\"33\" /><item2 xx=\"34\" /></data>");
            var docNav = doc.CreateNavigator();
            var docIter = docNav.Select("//item2 [@xx=33]");
            Assert.AreEqual(1, docIter.Count);
            Assert.AreEqual("", docIter.Current.Name);
            docIter.MoveNext();
            Assert.AreEqual("item2", docIter.Current.Name);

            var iterator = nav.Select("//item2 [@xx=33]");
            Assert.AreEqual(1, iterator.Count);
            Assert.AreEqual("", iterator.Current.Name);
            iterator.MoveNext();
            Assert.AreEqual("item2", iterator.Current.Name);
        }
        void DebugCreate(NavigableNavigator nav)
        {
#if DEBUG
            Debug("Create: [NavigableNavigator::{0}]", nav._uid);
#endif
        }
        /// <summary>
        /// Creates a new XPathNavigator using the same source but positioned at a new root.
        /// </summary>
        /// <returns>A new XPathNavigator using the same source and positioned at a new root.</returns>
        /// <remarks>The new root can be above this navigator's root.</remarks>
        public XPathNavigator CloneWithNewRoot(string id)
        {
            DebugEnter("CloneWithNewRoot");

            int contentId;
            State state = null;

            if (id != null && id.Trim() == "-1")
            {
                state = new State(_source.Root, null, null, 0, StatePosition.Root);
            }
            else if (int.TryParse(id, out contentId))
            {
                var content = _source.Get(contentId);
                if (content != null)
                {
                    state = new State(content, null, null, 0, StatePosition.Root);
                }
            }

            NavigableNavigator clone = null;

            if (state != null)
            {
                clone = new NavigableNavigator(_source, _nameTable, state);
                DebugCreate(clone);
                DebugReturn("[XPathNavigator]");
            }
            else
            {
                DebugReturn("[null]");                
            }

            return clone;
        }
 public void SelectByIdWithVariable(int id)
 {
     var source = new TestSource5();
     var nav = new NavigableNavigator(source);
     
     var iter = nav.Select("//* [@id=$id]", new XPathVariable("id", id.ToString(CultureInfo.InvariantCulture)));
     Assert.IsTrue(iter.MoveNext());
     var current = iter.Current as NavigableNavigator;
     Assert.AreEqual(NavigableNavigator.StatePosition.Element, current.InternalState.Position);
     Assert.AreEqual(id, (current.UnderlyingObject as TestContent).Id);
 }
        public void RootedNavigator()
        {
            var source = new TestSource5();
            var nav = new NavigableNavigator(source, source.Get(1));

            // go to (/root) /1
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(1, (nav.UnderlyingObject as TestContent).Id);

            // go to (/root) /1/prop1
            Assert.IsTrue(nav.MoveToFirstChild());
            // go to (/root) /1/prop2
            Assert.IsTrue(nav.MoveToNext());
            // go to (/root) /1/3
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(3, (nav.UnderlyingObject as TestContent).Id);

            // go to (/root) /1
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(1, (nav.UnderlyingObject as TestContent).Id);

            // go to (/root) ie root
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Root, nav.InternalState.Position);
            Assert.IsFalse(nav.MoveToParent());

            // can't go there
            Assert.IsFalse(nav.MoveToId("2"));
        }
        public void NavigateMixed()
        {
            var source = new TestSource2();
            var nav = new NavigableNavigator(source);

            nav.MoveToRoot();
            nav.MoveToFirstChild();
            Assert.AreEqual("root", nav.Name);
            nav.MoveToFirstChild();
            Assert.AreEqual("type1", nav.Name); // our content
            nav.MoveToFirstChild();
            Assert.AreEqual("prop1", nav.Name); // our property
            Assert.AreEqual(XPathNodeType.Element, nav.NodeType);
            nav.MoveToFirstChild();

            // "<data><item1>poo</item1><item2 xx=\"33\" /><item2 xx=\"34\" /></data>"

            Assert.AreEqual(XPathNodeType.Element, nav.NodeType);
            Assert.AreEqual("data", nav.Name);

            nav.MoveToFirstChild();
            Assert.AreEqual(XPathNodeType.Element, nav.NodeType);
            Assert.AreEqual("item1", nav.Name);

            nav.MoveToNext();
            Assert.AreEqual(XPathNodeType.Element, nav.NodeType);
            Assert.AreEqual("item2", nav.Name);

            nav.MoveToParent();
            Assert.AreEqual(XPathNodeType.Element, nav.NodeType);
            Assert.AreEqual("data", nav.Name);

            nav.MoveToParent();
            Assert.AreEqual(XPathNodeType.Element, nav.NodeType);
            Assert.AreEqual("prop1", nav.Name);
        }
        public void Navigate()
        {
            var source = new TestSource1();
            var nav = new NavigableNavigator(source);

            nav.MoveToRoot();
            Assert.AreEqual("", nav.Name); // because we're at root
            nav.MoveToFirstChild();
            Assert.AreEqual("root", nav.Name);
            nav.MoveToFirstChild();
            Assert.AreEqual("type1", nav.Name); // our first content
            nav.MoveToFirstAttribute();
            Assert.AreEqual("id", nav.Name);
            Assert.AreEqual("1", nav.Value);
            nav.MoveToNextAttribute();
            Assert.AreEqual("prop1", nav.Name);
            Assert.AreEqual("1:p1", nav.Value);
            nav.MoveToNextAttribute();
            Assert.AreEqual("prop2", nav.Name);
            Assert.AreEqual("1:p2", nav.Value);
            Assert.IsFalse(nav.MoveToNextAttribute());
            nav.MoveToParent();
            nav.MoveToFirstChild();
            Assert.AreEqual("prop3", nav.Name);
            Assert.AreEqual("1:p3", nav.Value);

            Assert.IsFalse(nav.MoveToNext());
        }
 /// <summary>
 /// Creates a new XPathNavigator positioned at the same node as this XPathNavigator.
 /// </summary>
 /// <returns>A new XPathNavigator positioned at the same node as this XPathNavigator.</returns>
 public override XPathNavigator Clone()
 {
     DebugEnter("Clone");
     var nav = new NavigableNavigator(_source, _nameTable, _state.Clone());
     DebugCreate(nav);
     DebugReturn("[XPathNavigator]");
     return nav;
 }
        public void CloneIsSafe()
        {
            var source = new TestSource5();
            var nav = new NavigableNavigator(source);
            TestContent content;

            Assert.AreEqual(NavigableNavigator.StatePosition.Root, nav.InternalState.Position);
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual("root", nav.Name); // at -1
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(1, (nav.UnderlyingObject as TestContent).Id);
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual(NavigableNavigator.StatePosition.PropertyElement, nav.InternalState.Position);
            Assert.AreEqual("prop1", nav.Name);
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual(NavigableNavigator.StatePosition.PropertyElement, nav.InternalState.Position);
            Assert.AreEqual("prop2", nav.Name);
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(3, (nav.UnderlyingObject as TestContent).Id);

            // at that point nav is at /root/1/3

            var clone = nav.Clone() as NavigableNavigator;

            // move nav to /root/1/5 and ensure that clone stays at /root/1/3
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(5, (nav.UnderlyingObject as TestContent).Id);
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, clone.InternalState.Position);
            Assert.AreEqual(3, (clone.UnderlyingObject as TestContent).Id);

            // move nav to /root/2
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(1, (nav.UnderlyingObject as TestContent).Id);
            Assert.IsTrue(nav.MoveToNext());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(2, (nav.UnderlyingObject as TestContent).Id);
            Assert.IsTrue(nav.MoveToFirstChild());
            Assert.AreEqual(NavigableNavigator.StatePosition.PropertyElement, nav.InternalState.Position);
            Assert.AreEqual("prop1", nav.Name);
            Assert.AreEqual("p21", nav.Value);

            // move clone to .. /root/1
            Assert.IsTrue(clone.MoveToParent());

            // clone has not been corrupted by nav
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, clone.InternalState.Position);
            Assert.AreEqual(1, (clone.UnderlyingObject as TestContent).Id);
        }
Exemple #22
0
        // add parameters to the macro parameters collection
        private void AddMacroParameter(ICollection<MacroNavigator.MacroParameter> parameters,
            NavigableNavigator contentNavigator, NavigableNavigator mediaNavigator,
            string macroPropertyAlias,string macroPropertyType, string macroPropertyValue)
        {
            // if no value is passed, then use the current "pageID" as value
            var contentId = macroPropertyValue == string.Empty ? UmbracoContext.Current.PageId.ToString() : macroPropertyValue;

	        TraceInfo("umbracoMacro",
	                  "Xslt node adding search start (" + macroPropertyAlias + ",'" +
	                  macroPropertyValue + "')");

            // beware! do not use the raw content- or media- navigators, but clones !!

            switch (macroPropertyType)
            {
                case "contentTree":
                    parameters.Add(new MacroNavigator.MacroParameter(
                        macroPropertyAlias,
                        contentNavigator.CloneWithNewRoot(contentId), // null if not found - will be reported as empty
                        attributes: new Dictionary<string, string> { { "nodeID", contentId } }));

                    break;

                case "contentPicker":
                    parameters.Add(new MacroNavigator.MacroParameter(
                        macroPropertyAlias,
                        contentNavigator.CloneWithNewRoot(contentId), // null if not found - will be reported as empty
                        0));
                    break;

                case "contentSubs":
                    parameters.Add(new MacroNavigator.MacroParameter(
                        macroPropertyAlias,
                        contentNavigator.CloneWithNewRoot(contentId), // null if not found - will be reported as empty
                        1));
                    break;

                case "contentAll":
                    parameters.Add(new MacroNavigator.MacroParameter(macroPropertyAlias, contentNavigator.Clone()));
                    break;

                case "contentRandom":
                    var nav = contentNavigator.Clone();
                    if (nav.MoveToId(contentId))
                    {
                        var descendantIterator = nav.Select("./* [@isDoc]");
                        if (descendantIterator.MoveNext())
                        {
                            // not empty - and won't change
                            var descendantCount = descendantIterator.Count;

                            int index;
                            var r = library.GetRandom();
                            lock (r)
                            {
                                index = r.Next(descendantCount);
                            }

                            while (index > 0 && descendantIterator.MoveNext())
                                index--;

                            var node = descendantIterator.Current.UnderlyingObject as INavigableContent;
                            if (node != null)
                            {
                                nav = contentNavigator.CloneWithNewRoot(node.Id.ToString(CultureInfo.InvariantCulture));
                                parameters.Add(new MacroNavigator.MacroParameter(macroPropertyAlias, nav, 0));                                
                            }
                            else
                                throw new InvalidOperationException("Iterator contains non-INavigableContent elements.");
                        }
                        else
							TraceWarn("umbracoMacro",
									  "Error adding random node - parent (" + macroPropertyValue +
									  ") doesn't have children!");
                    }
                    else
                        TraceWarn("umbracoMacro",
                                  "Error adding random node - parent (" + macroPropertyValue +
                                  ") doesn't exists!");
                    break;

                case "mediaCurrent":
                    parameters.Add(new MacroNavigator.MacroParameter(
                        macroPropertyAlias,
                        mediaNavigator.CloneWithNewRoot(contentId), // null if not found - will be reported as empty
                        0));
                    break;

                default:
                    parameters.Add(new MacroNavigator.MacroParameter(macroPropertyAlias, HttpContext.Current.Server.HtmlDecode(macroPropertyValue)));
                    break;
            }
        }
        public void SelectById(int id)
        {
            var source = new TestSource5();
            var nav = new NavigableNavigator(source);

            var iter = nav.Select(string.Format("//* [@id={0}]", id));
            Assert.IsTrue(iter.MoveNext());
            var current = iter.Current as NavigableNavigator;
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, current.InternalState.Position);
            Assert.AreEqual(id, (current.UnderlyingObject as TestContent).Id);
        }
        void DebugCreate(NavigableNavigator nav)
        {
#if DEBUGNAVIGATOR
            Debug("Create: [NavigableNavigator::{0}]", nav._uid);
#endif
        }
        public void MoveToId()
        {
            var source = new TestSource5();
            var nav = new NavigableNavigator(source);

            // move to /root/1/3
            Assert.IsTrue(nav.MoveToId("3"));
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(3, (nav.UnderlyingObject as TestContent).Id);

            // move to /root/1
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(1, (nav.UnderlyingObject as TestContent).Id);

            // move to /root
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(-1, (nav.UnderlyingObject as TestContent).Id);

            // move up
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Root, nav.InternalState.Position);
            Assert.IsFalse(nav.MoveToParent());

            // move to /root/1
            Assert.IsTrue(nav.MoveToId("1"));
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(1, (nav.UnderlyingObject as TestContent).Id);

            // move to /root
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(-1, (nav.UnderlyingObject as TestContent).Id);

            // move up
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Root, nav.InternalState.Position);
            Assert.IsFalse(nav.MoveToParent());

            // move to /root
            Assert.IsTrue(nav.MoveToId("-1"));
            Assert.AreEqual(NavigableNavigator.StatePosition.Element, nav.InternalState.Position);
            Assert.AreEqual(-1, (nav.UnderlyingObject as TestContent).Id);

            // move up
            Assert.IsTrue(nav.MoveToParent());
            Assert.AreEqual(NavigableNavigator.StatePosition.Root, nav.InternalState.Position);
            Assert.IsFalse(nav.MoveToParent());

            // get lost
            Assert.IsFalse(nav.MoveToId("666"));
        }
        public void OuterXmlBasic()
        {
            const string xml = @"<root id=""-1"" />";

            var doc = XmlHelper.CreateXPathDocument(xml);
            var nnav = doc.CreateNavigator();
            Assert.AreEqual(xml, nnav.OuterXml);

            var source = new TestSource0();
            var nav = new NavigableNavigator(source);
            Assert.AreEqual(xml, nav.OuterXml);
        }
        public void XsltDebugModeAndSortOrder(bool native, bool debug)
        {
            const string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<root>
    <node id=""1"" isDoc=""1"">
        <title>title-1</title>
        <node id=""3"" isDoc=""1"">
            <title>title-3</title>
            <node id=""7"" isDoc=""1"">
                <title>title-7</title>
            </node>
            <node id=""8"" isDoc=""1"">
                <title>title-8</title>
            </node>
        </node>
        <node id=""5"" isDoc=""1"">
            <title>title-5</title>
        </node>
    </node>
    <node id=""2"" isDoc=""1"">
        <title>title-2</title>
        <node id=""4"" isDoc=""1"">
            <title>title-4</title>
        </node>
        <node id=""6"" isDoc=""1"">
            <title>title-6</title>
        </node>
    </node>
</root>
";

            const string xslt = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE xsl:stylesheet [
    <!ENTITY nbsp ""&#x00A0;"">
]>
<xsl:stylesheet
  version=""1.0""
  xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""
  xmlns:msxml=""urn:schemas-microsoft-com:xslt""
	xmlns:umbraco.library=""urn:umbraco.library"" xmlns:Exslt.ExsltCommon=""urn:Exslt.ExsltCommon"" xmlns:Exslt.ExsltDatesAndTimes=""urn:Exslt.ExsltDatesAndTimes"" xmlns:Exslt.ExsltMath=""urn:Exslt.ExsltMath"" xmlns:Exslt.ExsltRegularExpressions=""urn:Exslt.ExsltRegularExpressions"" xmlns:Exslt.ExsltStrings=""urn:Exslt.ExsltStrings"" xmlns:Exslt.ExsltSets=""urn:Exslt.ExsltSets"" xmlns:Examine=""urn:Examine"" 
	exclude-result-prefixes=""msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets Examine "">

    <xsl:output method=""xml"" omit-xml-declaration=""yes"" />
    <xsl:param name=""currentPage""/>

    <xsl:template match=""/"">
		<!-- <xsl:for-each select=""/root/* [@isDoc]""> -->
        <!-- <xsl:for-each select=""$currentPage/root/* [@isDoc]""> -->
        <xsl:for-each select=""/macro/nav/root/* [@isDoc]"">
<xsl:text>! </xsl:text><xsl:value-of select=""title"" /><xsl:text>
</xsl:text>
			<xsl:for-each select=""./* [@isDoc]"">
<xsl:text>!! </xsl:text><xsl:value-of select=""title"" /><xsl:text>
</xsl:text>
    			<xsl:for-each select=""./* [@isDoc]"">
<xsl:text>!!! </xsl:text><xsl:value-of select=""title"" /><xsl:text>
</xsl:text>
	    		</xsl:for-each>
			</xsl:for-each>
		</xsl:for-each>
    </xsl:template>

</xsl:stylesheet>
";
            const string expected = @"! title-1
!! title-3
!!! title-7
!!! title-8
!! title-5
! title-2
!! title-4
!! title-6
";

            // see http://www.onenaught.com/posts/352/xslt-performance-tip-dont-indent-output
            // why aren't we using an XmlWriter here?

            var transform = new XslCompiledTransform(debug);
            var xmlReader = new XmlTextReader(new StringReader(xslt))
                {
                    EntityHandling = EntityHandling.ExpandEntities
                };
            var xslResolver = new XmlUrlResolver
                {
                    Credentials = CredentialCache.DefaultCredentials
                };
            var args = new XsltArgumentList();

            // .Default is more restrictive than .TrustedXslt
            transform.Load(xmlReader, XsltSettings.Default, xslResolver);

            XPathNavigator macro;
            if (!native)
            {
                var source = new TestSource7();
                var nav = new NavigableNavigator(source);
                //args.AddParam("currentPage", string.Empty, nav.Clone());

                var x = new XmlDocument();
                x.LoadXml(xml);
                
                macro = new MacroNavigator(new[]
                {
                    // it even fails like that => macro nav. issue?
                    new MacroNavigator.MacroParameter("nav", x.CreateNavigator()) // nav.Clone())
                }
                );
            }
            else
            {
                var doc = new XmlDocument();
                doc.LoadXml("<macro />");
                var nav = doc.CreateElement("nav");
                doc.DocumentElement.AppendChild(nav);
                var x = new XmlDocument();
                x.LoadXml(xml);
                nav.AppendChild(doc.ImportNode(x.DocumentElement, true));
                macro = doc.CreateNavigator();
            }

            var writer = new StringWriter();
            transform.Transform(macro, args, writer);

            // this was working with native, debug and non-debug
            // this was working with macro nav, non-debug
            // but was NOT working (changing the order of nodes) with macro nav, debug
            // was due to an issue with macro nav IsSamePosition, fixed

            //Console.WriteLine("--------");
            //Console.WriteLine(writer.ToString());
            Assert.AreEqual(expected.Lf(), writer.ToString().Lf());
        }
        public void OuterXml()
        {
            var source = new TestSource1();
            var nav = new NavigableNavigator(source);

            const string xml = @"<root id=""-1"" prop1="""" prop2="""">
  <type1 id=""1"" prop1=""1:p1"" prop2=""1:p2"">
    <prop3>1:p3</prop3>
  </type1>
</root>";

            Assert.AreEqual(xml.Lf(), nav.OuterXml.Lf());
        }
        public void WhiteSpacesAndEmptyValues()
        {

            // "When Microsoft’s DOM builder receives a text node from the parser
            // that contains only white space, it is thrown away." - so if it's ONLY
            // spaces, it's nothing, but spaces are NOT trimmed.

            // For attributes, spaces are preserved even when there's only spaces.

            var doc = XmlHelper.CreateXPathDocument(@"<root>
                        <item><prop/></item>
                        <item><prop></prop></item>
                        <item><prop> </prop></item>
                        <item><prop> 
                            </prop></item>
                        <item><prop> ooo </prop></item>
                        <item><prop> ooo 
                            </prop></item>
                        <item x=""""/>
                        <item x="" ""/>
                    </root>");

            var docNav = doc.CreateNavigator();

            Assert.AreEqual(@"<root>
  <item>
    <prop />
  </item>
  <item>
    <prop></prop>
  </item>
  <item>
    <prop></prop>
  </item>
  <item>
    <prop></prop>
  </item>
  <item>
    <prop> ooo </prop>
  </item>
  <item>
    <prop> ooo 
                            </prop>
  </item>
  <item x="""" />
  <item x="" "" />
</root>".Lf(), docNav.OuterXml.Lf());

            docNav.MoveToRoot();
            Assert.IsTrue(docNav.MoveToFirstChild());
            Assert.IsTrue(docNav.MoveToFirstChild());
            Assert.IsTrue(docNav.MoveToFirstChild()); // prop
            Assert.IsTrue(docNav.IsEmptyElement);
            Assert.IsTrue(docNav.MoveToParent());
            Assert.IsTrue(docNav.MoveToNext());
            Assert.IsTrue(docNav.MoveToFirstChild()); // prop
            Assert.IsFalse(docNav.IsEmptyElement);
            Assert.AreEqual("", docNav.Value); // contains an empty text node
            Assert.IsTrue(docNav.MoveToParent());
            Assert.IsTrue(docNav.MoveToNext());
            Assert.IsTrue(docNav.MoveToFirstChild()); // prop
            Assert.IsFalse(docNav.IsEmptyElement);
            Assert.AreEqual("", docNav.Value); // contains an empty text node

            var source = new TestSource8();
            var nav = new NavigableNavigator(source);

            // shows how whitespaces are handled by NavigableNavigator
            Assert.AreEqual(@"<root id=""-1"" attr="""">
  <item id=""1"" attr="""">
    <prop />
  </item>
  <item id=""2"" attr="""">
    <prop></prop>
  </item>
  <item id=""3"" attr=""   "">
    <prop>   </prop>
  </item>
  <item id=""4"" attr="""">
    <prop>
</prop>
  </item>
  <item id=""5"" attr=""  ooo  "">
    <prop>   ooo   </prop>
  </item>
</root>".Lf(), nav.OuterXml.Lf());
        }
        public void OuterXmlMixed()
        {
            var source = new TestSource2();
            var nav = new NavigableNavigator(source);

            nav.MoveToRoot();

            const string outerXml = @"<root id=""-1"">
  <type1 id=""1"">
    <prop1>
      <data>
        <item1>poo</item1>
        <item2 xx=""33"" />
        <item2 xx=""34"" />
      </data>
    </prop1>
  </type1>
</root>";

            Assert.AreEqual(outerXml.Lf(), nav.OuterXml.Lf());
        }