Beispiel #1
0
        /// <summary>
        /// Returns a filtered collection of the descendant elements for this document
        /// or element, in document order. Only elements that have a matching System.Xml.Linq.XName
        /// are included in the collection.
        /// </summary>
        /// <param name="name">The System.Xml.Linq.XName to match.</param>
        /// <returns>
        /// An System.Collections.Generic.IEnumerable`1 of System.Xml.Linq.XElement
        /// containing the descendant elements of the System.Xml.Linq.XContainer that
        /// match the specified System.Xml.Linq.XName.
        /// </returns>
        public IEnumerable <XElement> Descendants(XName name)
        {
            //this one is much simpler than Elements since we can call the getElementsByTagName method that does exactly what we want.
            object jsNodesForElement = CSHTML5.Interop.ExecuteJavaScript("$0.getElementsByTagName($1)", INTERNAL_jsnode, name.ToString());

            if (XDocument.IsNullOrUndefined(jsNodesForElement)) //no children.
            {
                yield break;
            }

            int i = 0;

            while (true)
            {
                object nodeAtI = CSHTML5.Interop.ExecuteJavaScript("$0[$1]", jsNodesForElement, i);
                if (CSHTML5.Interop.IsUndefined(nodeAtI))
                {
                    break;
                }

                //note: they have a tagName so they are definitely XElements.
                yield return((XElement)XDocument.GetXNodeFromJSNode(nodeAtI));

                ++i;
            }
            yield break;
        }
Beispiel #2
0
        /// <summary>
        /// Returns a collection of the child elements of this element or document, in
        /// document order.
        /// </summary>
        /// <returns>
        /// An System.Collections.Generic.IEnumerable&lt;XElement&gt; of System.Xml.Linq.XElement
        /// containing the child elements of this System.Xml.Linq.XContainer, in document
        /// order.
        /// </returns>
        public IEnumerable <XElement> Elements()
        {
            //Note on the JS below: the filter is to get rid of the XText elements which have no tagName.

            //object jsNodesForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(node => node.tagName !== undefined)", INTERNAL_jsnode);
            //todo: check whether the line above is more efficient than the line below and change accordingly (if IE allows it, see todo in Elements(XName))
            object jsNodesForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(function(node) { return node.tagName !== undefined})", INTERNAL_jsnode);

            if (XDocument.IsNullOrUndefined(jsNodesForElement))
            {
                yield break; // no children.
            }

            int i = 0;

            while (true)
            {
                object nodeAtI = CSHTML5.Interop.ExecuteJavaScript("$0[$1]", jsNodesForElement, i);
                if (CSHTML5.Interop.IsUndefined(nodeAtI))
                {
                    break;
                }

                //note: they have a tagName so they are definitely XElements.
                yield return((XElement)XDocument.GetXNodeFromJSNode(nodeAtI));

                ++i;
            }
            yield break;
        }
Beispiel #3
0
        /// <summary>
        /// Gets the first (in document order) child element with the specified System.Xml.Linq.XName.
        /// </summary>
        /// <param name="name">The System.Xml.Linq.XName to match.</param>
        /// <returns>
        /// A System.Xml.Linq.XElement that matches the specified System.Xml.Linq.XName,
        /// or null.
        /// </returns>
        public XElement Element(XName name)
        {
            //note: we couldn't use INTERNAL_jsnode.getElementsByTagName(name) because it returns the children of the children nodes as well (we only want the immediate children).

            //Note about the js below: Array.from is to get the possibility to call the filter method:

            string nameAsString      = name.LocalName;
            string namespaceAsString = name.NamespaceName;
            // object jsNodeForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(node => node.tagName == $1)[0]", INTERNAL_jsnode, name.ToString());
            //todo: check whether the line above is more efficient than the line below and change accordingly (if IE allows it, see todo in Elements(XName))
            // Note: below, the test ((!$2 && !node.namespaceURI) || node.namespaceURI == $2) can be read as both are null or empty, or they are the same. This way, the case one is null while the other is empty will still be considered a match.
            object jsNodeForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(function(node) { return (node.localName == $1 && ((!$2 && !node.namespaceURI) || node.namespaceURI == $2))})[0]", INTERNAL_jsnode, nameAsString, namespaceAsString); //}

            if (XDocument.IsNullOrUndefined(jsNodeForElement))                                                                                                                                                                                                                 //not found, we return null.
            {
                return(null);
            }

            XNode node = XDocument.GetXNodeFromJSNode(jsNodeForElement);

            if (node is XElement)
            {
                return((XElement)node);
            }
            return(null);
        }
Beispiel #4
0
        //todo: handle the comment nodes type XComment in c#
        //todo: change the way we determine the type of the nodes (cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType)
        //      basically, nodeType = : 1 is XElement, 3 is XText, 8 is XComment, 9 is XDocument but is useless I think

        /// <summary>
        /// Returns a collection of the child nodes of this element or document, in document
        /// order.
        /// </summary>
        /// <returns>
        /// An System.Collections.Generic.IEnumerable&lt;T&gt; of System.Xml.Linq.XNode containing
        /// the contents of this System.Xml.Linq.XContainer, in document order.
        /// </returns>
        public IEnumerable <XNode> Nodes()
        {
            int i = 0;

            while (true)
            {
                object nodeAtI = CSHTML5.Interop.ExecuteJavaScript("$0.childNodes[$1]", INTERNAL_jsnode, i);
                if (CSHTML5.Interop.IsUndefined(nodeAtI))
                {
                    break;
                }

                yield return(XDocument.GetXNodeFromJSNode(nodeAtI));

                ++i;
            }
            yield break;
        }
Beispiel #5
0
        /// <summary>
        /// Returns a filtered collection of the child elements of this element or document,
        /// in document order. Only elements that have a matching System.Xml.Linq.XName
        /// are included in the collection.
        /// </summary>
        /// <param name="name">The System.Xml.Linq.XName to match.</param>
        /// <returns>
        /// An System.Collections.Generic.IEnumerable`1 of System.Xml.Linq.XElement
        /// containing the children of the System.Xml.Linq.XContainer that have a matching
        /// System.Xml.Linq.XName, in document order.
        /// </returns>
        public IEnumerable <XElement> Elements(XName name)
        {
            //note: we couldn't use INTERNAL_jsnode.getElementsByTagName(name) because it returns the children of the children nodes as well (we only want the immediate children).

            //jsNodesForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(node => node.tagName == $1)", INTERNAL_jsnode, name.ToString());
            //todo: if IE learns that => isn't a syntax error (which breaks the whole file) and can use it properly, use the line above instead of the following because it seems to be more efficient.
            object jsNodesForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(document.functionToCompareWordForFilter($1))", INTERNAL_jsnode, name.ToString());

            #region explanation of the line above
            //note: normal use of filter: myArray.filter( function(node) { return testOnNode; })
            //problem here: testOnNode depends on the name than node and we cannot put $1 in there because JSIL changes it to "this.$name", but "this" does not exist where "testOnNode" is.
            //solution: document.functionToCompareWordForFilter(name) returns A FUNCTION that takes a node and compares its tagName to name (see in cshtml5.js)
            //          when calling document.functionToCompareWordForFilter, this.$name exists
            //          and the created method that is used by filter can use it normally.
            //in short: the function created by document.functionToCompareWordForFilter provides the name, filter provides the node.
            #endregion

            if (XDocument.IsNullOrUndefined(jsNodesForElement)) //nothing fits the request.
            {
                yield break;
            }

            int i = 0;

            while (true)
            {
                object nodeAtI = CSHTML5.Interop.ExecuteJavaScript("$0[$1]", jsNodesForElement, i);
                if (CSHTML5.Interop.IsUndefined(nodeAtI))
                {
                    break;
                }

                //note: they have a tagName so they are definitely XElements.
                yield return((XElement)XDocument.GetXNodeFromJSNode(nodeAtI));

                ++i;
            }
            yield break;
        }
Beispiel #6
0
        /// <summary>
        /// Gets the first (in document order) child element with the specified System.Xml.Linq.XName.
        /// </summary>
        /// <param name="name">The System.Xml.Linq.XName to match.</param>
        /// <returns>
        /// A System.Xml.Linq.XElement that matches the specified System.Xml.Linq.XName,
        /// or null.
        /// </returns>
        public XElement Element(XName name)
        {
            //note: we couldn't use INTERNAL_jsnode.getElementsByTagName(name) because it returns the children of the children nodes as well (we only want the immediate children).

            //Note about the js below: Array.from is to get the possibility to call the filter method:

            string nameAsString = name.LocalName;
            // object jsNodeForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(node => node.tagName == $1)[0]", INTERNAL_jsnode, name.ToString());
            //todo: check whether the line above is more efficient than the line below and change accordingly (if IE allows it, see todo in Elements(XName))
            object jsNodeForElement = CSHTML5.Interop.ExecuteJavaScript("Array.from($0.childNodes).filter(function(node) { return node.tagName == $1})[0]", INTERNAL_jsnode, nameAsString); //}

            if (XDocument.IsNullOrUndefined(jsNodeForElement))                                                                                                                              //not found, we return null.
            {
                return(null);
            }

            XNode node = XDocument.GetXNodeFromJSNode(jsNodeForElement);

            if (node is XElement)
            {
                return((XElement)node);
            }
            return(null);
        }