예제 #1
0
        /// <summary>
        /// Must be called when an element node's children have been fully enumerated.
        /// </summary>
        public void WriteEndElement(bool allowShortcutTag)
        {
            XPathNodeRef nodeRef;

            Debug.Assert(_pageParent != null && _pageParent[_idxParent].NodeType == XPathNodeType.Element);

            // If element has no content-typed children except for the one about to be added, then
            // its value is the same as its only text child's.
            if (!_pageParent[_idxParent].HasContentChild)
            {
                switch (_textBldr.TextType)
                {
                case TextBlockType.Text:
                    // Collapsed text node can be created if text line number information can be encoded efficiently in parent node
                    if (_lineInfo != null)
                    {
                        // If collapsed text node is not on same line as parent, don't collapse text
                        if (_textBldr.LineNumber != _pageParent[_idxParent].LineNumber)
                        {
                            goto case TextBlockType.Whitespace;
                        }

                        // If position is not within 256 of parent, don't collapse text
                        int posDiff = _textBldr.LinePosition - _pageParent[_idxParent].LinePosition;
                        if (posDiff < 0 || posDiff > XPathNode.MaxCollapsedPositionOffset)
                        {
                            goto case TextBlockType.Whitespace;
                        }

                        // Set collapsed node line position offset
                        _pageParent[_idxParent].SetCollapsedLineInfoOffset(posDiff);
                    }

                    // Set collapsed node text
                    _pageParent[_idxParent].SetCollapsedValue(_textBldr.ReadText());
                    break;

                case TextBlockType.SignificantWhitespace:
                case TextBlockType.Whitespace:
                    // Create separate whitespace node
                    CachedTextNode();
                    _pageParent[_idxParent].SetValue(_pageSibling[_idxSibling].Value);
                    break;

                default:
                    // Empty value, so don't create collapsed text node
                    _pageParent[_idxParent].SetEmptyValue(allowShortcutTag);
                    break;
                }
            }
            else
            {
                if (_textBldr.HasText)
                {
                    // Element's last child (one of several) is a text or whitespace node
                    CachedTextNode();
                }
            }

            // If namespaces were added to this element,
            if (_pageParent[_idxParent].HasNamespaceDecls)
            {
                // Add it to the document's element --> namespace mapping
                _doc.AddNamespace(_pageParent, _idxParent, _pageNmsp, _idxNmsp);

                // Restore the previous namespace chain
                nodeRef   = _stkNmsp.Pop();
                _pageNmsp = nodeRef.Page;
                _idxNmsp  = nodeRef.Index;
            }

            // Make parent of this element the current element
            _pageSibling = _pageParent;
            _idxSibling  = _idxParent;
            _idxParent   = _pageParent[_idxParent].GetParent(out _pageParent);
        }