diff options
author | Atsushi Eno <atsushieno@gmail.com> | 2005-03-22 10:04:18 +0300 |
---|---|---|
committer | Atsushi Eno <atsushieno@gmail.com> | 2005-03-22 10:04:18 +0300 |
commit | 15c121125e04e72d072c55656ed80545d2118ed6 (patch) | |
tree | aba14fcede8bcc55f05cbfd02b08a75f7e5419b6 /mcs/class/System.XML/Mono.Xml.XPath | |
parent | 71fe4a042410cedd8ec11ba321b37856d3870956 (diff) |
2004-03-22 Atsushi Enomoto <atsushi@ximian.com>
* DTMXPathDocumentBuilder.cs,
DTMXPathDocumentWriter.cs,
DTMXPathNavigator.cs,
DTMXPathNode.cs : updated to be equivalent to DTMXPathNavigator2.
* DTMXPathDocumentBuilder2.cs :
String pool is now under index based management. For nonAtomicIndex
string, don't try all the entries the pool holds. It causes
significant performance loss for large documents.
* DTMXPathDocument.cs,
DTMXPathDocument2.cs : removed unused fields (warning elimination).
svn path=/trunk/mcs/; revision=42057
Diffstat (limited to 'mcs/class/System.XML/Mono.Xml.XPath')
8 files changed, 191 insertions, 259 deletions
diff --git a/mcs/class/System.XML/Mono.Xml.XPath/ChangeLog b/mcs/class/System.XML/Mono.Xml.XPath/ChangeLog index 087e19444a8..d0d8a26695d 100644 --- a/mcs/class/System.XML/Mono.Xml.XPath/ChangeLog +++ b/mcs/class/System.XML/Mono.Xml.XPath/ChangeLog @@ -1,3 +1,16 @@ +2004-03-22 Atsushi Enomoto <atsushi@ximian.com> + + * DTMXPathDocumentBuilder.cs, + DTMXPathDocumentWriter.cs, + DTMXPathNavigator.cs, + DTMXPathNode.cs : updated to be equivalent to DTMXPathNavigator2. + * DTMXPathDocumentBuilder2.cs : + String pool is now under index based management. For nonAtomicIndex + string, don't try all the entries the pool holds. It causes + significant performance loss for large documents. + * DTMXPathDocument.cs, + DTMXPathDocument2.cs : removed unused fields (warning elimination). + 2004-03-16 Atsushi Enomoto <atsushi@ximian.com> * Pattern.cs : fixed incorrect optimization. diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs index d7b2911e1ca..4f0a80112c1 100644 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs @@ -42,56 +42,26 @@ namespace Mono.Xml.XPath class DTMXPathDocument : IXPathNavigable { -#region ctor. - public DTMXPathDocument (XmlNameTable nameTable, DTMXPathLinkedNode [] nodes, DTMXPathAttributeNode [] attributes, DTMXPathNamespaceNode [] namespaces, Hashtable idTable) { - this.nameTable = nameTable; - this.nodes = nodes; - this.attributes = attributes; - this.namespaces = namespaces; - this.idTable = idTable; + root = new DTMXPathNavigator (this, + nameTable, + nodes, + attributes, + namespaces, + idTable); } -#endregion - - -#region Methods public XPathNavigator CreateNavigator () { - if (root == null) { - root = new DTMXPathNavigator (this, - nameTable, - nodes, - attributes, - namespaces, - idTable); - } return root.Clone (); } -#endregion - - XmlNameTable nameTable; - - // Root XPathNavigator. - DTMXPathNavigator root; - -#region Immutable tree fields - - DTMXPathLinkedNode [] nodes = new DTMXPathLinkedNode [0]; - DTMXPathAttributeNode [] attributes = new DTMXPathAttributeNode [0]; - DTMXPathNamespaceNode [] namespaces = new DTMXPathNamespaceNode [0]; - - // idTable [string value] -> int nodeId - readonly Hashtable idTable; - -#endregion - + XPathNavigator root; } } diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs index b51e8a5a6ce..43fa3d80759 100755 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs @@ -42,8 +42,6 @@ namespace Mono.Xml.XPath class DTMXPathDocument2 : IXPathNavigable { -#region ctor. - public DTMXPathDocument2 (XmlNameTable nameTable, DTMXPathLinkedNode2 [] nodes, DTMXPathAttributeNode2 [] attributes, @@ -52,14 +50,6 @@ namespace Mono.Xml.XPath string [] nonAtomicStringPool, Hashtable idTable) { - this.nameTable = nameTable; - this.nodes = nodes; - this.attributes = attributes; - this.namespaces = namespaces; - this.atomicStringPool = atomicStringPool; - this.nonAtomicStringPool = nonAtomicStringPool; - this.idTable = idTable; - root = new DTMXPathNavigator2 (this, nameTable, nodes, @@ -70,37 +60,12 @@ namespace Mono.Xml.XPath idTable); } -#endregion - - -#region Methods public XPathNavigator CreateNavigator () { return root.Clone (); } -#endregion - - readonly XmlNameTable nameTable; - - // Root XPathNavigator. - readonly DTMXPathNavigator2 root; - -#region Immutable tree fields - - readonly DTMXPathLinkedNode2 [] nodes; - readonly DTMXPathAttributeNode2 [] attributes; - readonly DTMXPathNamespaceNode2 [] namespaces; - - // String pool - readonly string [] atomicStringPool; - readonly string [] nonAtomicStringPool; - - // idTable [string value] -> int nodeId - readonly Hashtable idTable; - -#endregion - + XPathNavigator root; } } diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs index 65bb3c35aae..b635a6360be 100644 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs @@ -91,11 +91,12 @@ namespace Mono.Xml.XPath this.nameTable = reader.NameTable; nodeCapacity = defaultCapacity; attributeCapacity = nodeCapacity; + nsCapacity = 10; idTable = new Hashtable (); nodes = new DTMXPathLinkedNode [nodeCapacity]; attributes = new DTMXPathAttributeNode [attributeCapacity]; - namespaces = new DTMXPathNamespaceNode [0]; + namespaces = new DTMXPathNamespaceNode [nsCapacity]; Compile (); } @@ -105,9 +106,9 @@ namespace Mono.Xml.XPath XmlSpace xmlSpace; XmlNameTable nameTable; IXmlLineInfo lineInfo; - int nodeCapacity = 200; - int attributeCapacity = 200; - int nsCapacity = 10; + int nodeCapacity; + int attributeCapacity; + int nsCapacity; // Linked Node DTMXPathLinkedNode [] nodes; @@ -124,18 +125,19 @@ namespace Mono.Xml.XPath int nodeIndex; int attributeIndex; int nsIndex; - int parentForFirstChild; // for attribute processing; should be reset per each element. - int firstAttributeIndex; - int lastNsIndexInCurrent; + bool hasAttributes; + bool hasLocalNs; int attrIndexAtStart; int nsIndexAtStart; - int prevSibling; int lastNsInScope; bool skipRead = false; + int [] parentStack = new int [10]; + int parentStackIndex = 0; + public DTMXPathDocument CreateDocument () { return new DTMXPathDocument (nameTable, @@ -151,7 +153,7 @@ namespace Mono.Xml.XPath // index 0 is dummy. No node (including Root) is assigned to this index // So that we can easily compare index != 0 instead of index < 0. // (Difference between jnz or jbe in 80x86.) - AddNode (0, 0, 0, 0, XPathNodeType.All, "", false, "", "", "", "", "", 0, 0, 0); + AddNode (0, 0, 0, XPathNodeType.All, "", false, "", "", "", "", "", 0, 0, 0); nodeIndex++; AddAttribute (0, null, null, null, null, 0, 0); AddNsNode (0, null, null, 0); @@ -159,11 +161,11 @@ namespace Mono.Xml.XPath AddNsNode (1, "xml", XmlNamespaces.XML, 0); // add root. - AddNode (0, 0, 0, -1, XPathNodeType.Root, xmlReader.BaseURI, false, "", "", "", "", "", 1, 0, 0); + AddNode (0, 0, 0, XPathNodeType.Root, xmlReader.BaseURI, false, "", "", "", "", "", 1, 0, 0); this.nodeIndex = 1; this.lastNsInScope = 1; - this.parentForFirstChild = nodeIndex; + parentStack [0] = nodeIndex; while (!xmlReader.EOF) Read (); @@ -180,15 +182,9 @@ namespace Mono.Xml.XPath if (!xmlReader.Read ()) return; skipRead = false; - int parent = nodeIndex; - - if (nodes [nodeIndex].Depth >= xmlReader.Depth) { - // if not, then current node is parent. - while (xmlReader.Depth <= nodes [parent].Depth) - parent = nodes [parent].Parent; - } + int parent = parentStack [parentStackIndex]; + int prevSibling = nodeIndex; - prevSibling = nodeIndex; switch (xmlReader.NodeType) { case XmlNodeType.Element: case XmlNodeType.CDATA: @@ -196,17 +192,17 @@ namespace Mono.Xml.XPath case XmlNodeType.Comment: case XmlNodeType.Text: case XmlNodeType.ProcessingInstruction: - if (parentForFirstChild >= 0) + if (parent == nodeIndex) prevSibling = 0; else - while (nodes [prevSibling].Depth != xmlReader.Depth) + while (nodes [prevSibling].Parent != parent) prevSibling = nodes [prevSibling].Parent; nodeIndex++; if (prevSibling != 0) nodes [prevSibling].NextSibling = nodeIndex; - if (parentForFirstChild >= 0) + if (parentStack [parentStackIndex] == nodeIndex - 1) nodes [parent].FirstChild = nodeIndex; break; case XmlNodeType.Whitespace: @@ -215,33 +211,31 @@ namespace Mono.Xml.XPath else goto default; case XmlNodeType.EndElement: - parentForFirstChild = -1; + parentStackIndex--; return; default: // No operations. Doctype, EntityReference, return; } - parentForFirstChild = -1; // Might be changed in ProcessElement(). - string value = null; - XPathNodeType nodeType = xmlReader.NodeType == XmlNodeType.Whitespace ? - XPathNodeType.Whitespace : XPathNodeType.Text; + XPathNodeType nodeType = XPathNodeType.Text; switch (xmlReader.NodeType) { case XmlNodeType.Element: ProcessElement (parent, prevSibling); break; - case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: - case XmlNodeType.Text: + nodeType = XPathNodeType.SignificantWhitespace; + goto case XmlNodeType.Text; case XmlNodeType.Whitespace: - if (value == null) - skipRead = true; + nodeType = XPathNodeType.Whitespace; + goto case XmlNodeType.Text; + case XmlNodeType.CDATA: + case XmlNodeType.Text: AddNode (parent, 0, prevSibling, - xmlReader.Depth, nodeType, xmlReader.BaseURI, xmlReader.IsEmptyElement, @@ -253,10 +247,37 @@ namespace Mono.Xml.XPath nsIndex, lineInfo != null ? lineInfo.LineNumber : 0, lineInfo != null ? lineInfo.LinePosition : 0); - // this code is tricky, but after ReadString() invokation, - // xmlReader is moved to next node!! - if (value == null) - nodes [nodeIndex].Value = xmlReader.ReadString (); + // this code is tricky, but after sequential + // Read() invokation, xmlReader is moved to + // next node. + if (value == null) { + bool loop = true; + value = String.Empty; + XPathNodeType type = XPathNodeType.Whitespace; + do { + switch (xmlReader.NodeType) { + case XmlNodeType.Text: + case XmlNodeType.CDATA: + type = XPathNodeType.Text; + goto case XmlNodeType.Whitespace; + case XmlNodeType.SignificantWhitespace: + if (type == XPathNodeType.Whitespace) + type = XPathNodeType.SignificantWhitespace; + goto case XmlNodeType.Whitespace; + case XmlNodeType.Whitespace: + if (xmlReader.NodeType != XmlNodeType.Whitespace || xmlSpace == XmlSpace.Preserve) + value += xmlReader.Value; + loop = xmlReader.Read (); + skipRead = true; + continue; + default: + loop = false; + break; + } + } while (loop); + nodes [nodeIndex].Value = value; + nodes [nodeIndex].NodeType = type; + } break; case XmlNodeType.Comment: value = xmlReader.Value; @@ -292,8 +313,8 @@ namespace Mono.Xml.XPath private void PrepareStartElement (int previousSibling) { - firstAttributeIndex = 0; - lastNsIndexInCurrent = 0; + hasAttributes = false; + hasLocalNs = false; attrIndexAtStart = attributeIndex; nsIndexAtStart = nsIndex; @@ -309,7 +330,6 @@ namespace Mono.Xml.XPath AddNode (parent, 0, // dummy:firstAttribute previousSibling, - xmlReader.Depth, XPathNodeType.Element, xmlReader.BaseURI, xmlReader.IsEmptyElement, @@ -330,24 +350,33 @@ namespace Mono.Xml.XPath nodes [nodeIndex].FirstAttribute = attrIndexAtStart + 1; if (nsIndexAtStart != nsIndex) { nodes [nodeIndex].FirstNamespace = nsIndex; - lastNsInScope = nsIndex; + if (!xmlReader.IsEmptyElement) + lastNsInScope = nsIndex; } - if (!nodes [nodeIndex].IsEmptyElement) - parentForFirstChild = nodeIndex; + if (!nodes [nodeIndex].IsEmptyElement) { + parentStackIndex++; + if (parentStack.Length == parentStackIndex) { + int [] tmp = new int [parentStackIndex * 2]; + Array.Copy (parentStack, tmp, parentStackIndex); + parentStack = tmp; + } + parentStack [parentStackIndex] = nodeIndex; + } } private void ProcessNamespace (string prefix, string ns) { - nsIndex++; + int nextTmp = hasLocalNs ? + nsIndex : nodes [nodeIndex].FirstNamespace; - int nextTmp = lastNsIndexInCurrent == 0 ? nodes [nodeIndex].FirstNamespace : lastNsIndexInCurrent; + nsIndex++; this.AddNsNode (nodeIndex, prefix, ns, nextTmp); - lastNsIndexInCurrent = nsIndex; + hasLocalNs = true; } private void ProcessAttribute (string prefix, string localName, string ns, string value) @@ -361,10 +390,10 @@ namespace Mono.Xml.XPath value, lineInfo != null ? lineInfo.LineNumber : 0, lineInfo != null ? lineInfo.LinePosition : 0); - if (firstAttributeIndex == 0) - firstAttributeIndex = attributeIndex; - else + if (hasAttributes) attributes [attributeIndex - 1].NextAttribute = attributeIndex; + else + hasAttributes = true; // Identity infoset if (validatingReader != null) { @@ -403,7 +432,7 @@ namespace Mono.Xml.XPath } // Here followings are skipped: firstChild, nextSibling, - public void AddNode (int parent, int firstAttribute, int previousSibling, int depth, XPathNodeType nodeType, string baseUri, bool isEmptyElement, string localName, string ns, string prefix, string value, string xmlLang, int namespaceNode, int lineNumber, int linePosition) + public void AddNode (int parent, int firstAttribute, int previousSibling, XPathNodeType nodeType, string baseUri, bool isEmptyElement, string localName, string ns, string prefix, string value, string xmlLang, int namespaceNode, int lineNumber, int linePosition) { if (nodes.Length < nodeIndex + 1) { nodeCapacity *= 4; @@ -418,7 +447,6 @@ namespace Mono.Xml.XPath nodes [nodeIndex].FirstAttribute = firstAttribute; nodes [nodeIndex].PreviousSibling = previousSibling; nodes [nodeIndex].NextSibling = 0; // dummy - nodes [nodeIndex].Depth = depth; nodes [nodeIndex].NodeType = nodeType; nodes [nodeIndex].BaseURI = baseUri; nodes [nodeIndex].IsEmptyElement = isEmptyElement; diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs index ca4266fcace..3c42eb99282 100755 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs @@ -122,7 +122,9 @@ namespace Mono.Xml.XPath // String pool string [] atomicStringPool; + int atomicIndex; string [] nonAtomicStringPool; + int nonAtomicIndex; // idTable [string value] -> int nodeId Hashtable idTable; @@ -162,6 +164,7 @@ namespace Mono.Xml.XPath atomicStringPool [1] = nonAtomicStringPool [1] = null; atomicStringPool [2] = nonAtomicStringPool [2] = XmlNamespaces.XML; atomicStringPool [3] = nonAtomicStringPool [3] = XmlNamespaces.XMLNS; + atomicIndex = nonAtomicIndex = 4; // index 0 is dummy. No node (including Root) is assigned to this index // So that we can easily compare index != 0 instead of index < 0. @@ -186,21 +189,12 @@ namespace Mono.Xml.XPath SetAttributeArrayLength (attributeIndex + 1); SetNsArrayLength (nsIndex + 1); - int i; - for (i = 3; i < atomicStringPool.Length; i++) { - if (atomicStringPool [i] == null) - break; - } - string [] newArr = new string [i]; - Array.Copy (atomicStringPool, newArr, i); + string [] newArr = new string [atomicIndex]; + Array.Copy (atomicStringPool, newArr, atomicIndex); atomicStringPool = newArr; - for (i = 3; i < nonAtomicStringPool.Length; i++) { - if (nonAtomicStringPool [i] == null) - break; - } - newArr = new string [i]; - Array.Copy (nonAtomicStringPool, newArr, i); + newArr = new string [nonAtomicIndex]; + Array.Copy (nonAtomicStringPool, newArr, nonAtomicIndex); nonAtomicStringPool = newArr; xmlReader = null; // It is no more required. @@ -445,20 +439,17 @@ namespace Mono.Xml.XPath if (s == null) return 1; int i = 2; - for (; i < atomicStringPool.Length; i++) { - if (atomicStringPool [i] == null) { - atomicStringPool [i] = s; - return i; - } - else if (Object.ReferenceEquals (s, - atomicStringPool [i])) + for (; i < atomicIndex; i++) + if (Object.ReferenceEquals (s, atomicStringPool [i])) return i; + + if (atomicIndex == atomicStringPool.Length) { + string [] newArr = new string [atomicIndex * 2]; + Array.Copy (atomicStringPool, newArr, atomicIndex); + atomicStringPool = newArr; } - string [] newArr = new string [i * 2]; - Array.Copy (atomicStringPool, newArr, i); - atomicStringPool = newArr; - atomicStringPool [i] = s; - return i; + atomicStringPool [atomicIndex] = s; + return atomicIndex++; } private int NonAtomicIndex (string s) @@ -468,19 +459,21 @@ namespace Mono.Xml.XPath if (s == null) return 1; int i = 2; - for (; i < nonAtomicStringPool.Length; i++) { - if (nonAtomicStringPool [i] == null) { - nonAtomicStringPool [i] = s; - return i; - } - else if (s == nonAtomicStringPool [i]) + + // Here we don't compare all the entries (sometimes it + // goes extremely slow). + int max = nonAtomicIndex < 100 ? nonAtomicIndex : 100; + for (; i < max; i++) + if (s == nonAtomicStringPool [i]) return i; + + if (nonAtomicIndex == nonAtomicStringPool.Length) { + string [] newArr = new string [nonAtomicIndex * 2]; + Array.Copy (nonAtomicStringPool, newArr, nonAtomicIndex); + nonAtomicStringPool = newArr; } - string [] newArr = new string [i * 2]; - Array.Copy (nonAtomicStringPool, newArr, i); - nonAtomicStringPool = newArr; - nonAtomicStringPool [i] = s; - return i; + nonAtomicStringPool [nonAtomicIndex] = s; + return nonAtomicIndex++; } private void SetNodeArrayLength (int size) diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs index 3688a99f555..be388f7bb98 100755 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs @@ -48,19 +48,20 @@ namespace Mono.Xml.XPath nameTable = nt == null ? new NameTable () : nt; nodeCapacity = defaultCapacity; attributeCapacity = nodeCapacity; + nsCapacity = 10; idTable = new Hashtable (); nodes = new DTMXPathLinkedNode [nodeCapacity]; attributes = new DTMXPathAttributeNode [attributeCapacity]; - namespaces = new DTMXPathNamespaceNode [0]; + namespaces = new DTMXPathNamespaceNode [nsCapacity]; Init (); } XmlNameTable nameTable; - int nodeCapacity = 200; - int attributeCapacity = 200; - int nsCapacity = 10; + int nodeCapacity; + int attributeCapacity; + int nsCapacity; // Linked Node DTMXPathLinkedNode [] nodes; @@ -77,19 +78,19 @@ namespace Mono.Xml.XPath int nodeIndex; int attributeIndex; int nsIndex; - int parentForFirstChild; + int [] parentStack = new int [10]; + int parentStackIndex = 0; // for attribute processing; should be reset per each element. - int firstAttributeIndex; - int lastNsIndexInCurrent; + bool hasAttributes; + bool hasLocalNs; int attrIndexAtStart; int nsIndexAtStart; - int prevSibling; int lastNsInScope; // They are only used in Writer - int writerDepth; + int prevSibling; WriteState state; bool openNamespace; bool isClosed; @@ -111,7 +112,7 @@ namespace Mono.Xml.XPath // index 0 is dummy. No node (including Root) is assigned to this index // So that we can easily compare index != 0 instead of index < 0. // (Difference between jnz or jbe in 80x86.) - AddNode (0, 0, 0, 0, XPathNodeType.All, "", false, "", "", "", "", "", 0, 0, 0); + AddNode (0, 0, 0, XPathNodeType.All, "", false, "", "", "", "", "", 0, 0, 0); nodeIndex++; AddAttribute (0, null, null, null, null, 0, 0); AddNsNode (0, null, null, 0); @@ -119,37 +120,28 @@ namespace Mono.Xml.XPath AddNsNode (1, "xml", XmlNamespaces.XML, 0); // add root. - AddNode (0, 0, 0, -1, XPathNodeType.Root, null, false, "", "", "", "", "", 1, 0, 0); + AddNode (0, 0, 0, XPathNodeType.Root, null, false, "", "", "", "", "", 1, 0, 0); this.nodeIndex = 1; this.lastNsInScope = 1; - this.parentForFirstChild = nodeIndex; + parentStack [0] = nodeIndex; state = WriteState.Content; } private int GetParentIndex () { - if (parentForFirstChild >= 0) - return parentForFirstChild; - - int parent = nodeIndex; - if (nodes [nodeIndex].Depth >= writerDepth) { - // if not, then current node is parent. - while (writerDepth <= nodes [parent].Depth) - parent = nodes [parent].Parent; - } - return parent; + return parentStack [parentStackIndex]; } private int GetPreviousSiblingIndex () { + int parent = parentStack [parentStackIndex]; + if (parent == nodeIndex) + return 0; int prevSibling = nodeIndex; - if (parentForFirstChild >= 0) - prevSibling = 0; - else - while (nodes [prevSibling].Depth != writerDepth) - prevSibling = nodes [prevSibling].Parent; + while (nodes [prevSibling].Parent != parent) + prevSibling = nodes [prevSibling].Parent; return prevSibling; } @@ -162,10 +154,8 @@ namespace Mono.Xml.XPath if (prevSibling != 0) nodes [prevSibling].NextSibling = nodeIndex; - if (parentForFirstChild >= 0) + if (parent == nodeIndex - 1) nodes [parent].FirstChild = nodeIndex; - - parentForFirstChild = -1; } private void CloseStartElement () @@ -177,11 +167,15 @@ namespace Mono.Xml.XPath lastNsInScope = nsIndex; } - if (!nodes [nodeIndex].IsEmptyElement) - parentForFirstChild = nodeIndex; + parentStackIndex++; + if (parentStack.Length == parentStackIndex) { + int [] tmp = new int [parentStackIndex * 2]; + Array.Copy (parentStack, tmp, parentStackIndex); + parentStack = tmp; + } + parentStack [parentStackIndex] = nodeIndex; state = WriteState.Content;
- writerDepth++; } #region Adding Nodes @@ -209,7 +203,7 @@ namespace Mono.Xml.XPath } // Here followings are skipped: firstChild, nextSibling, - public void AddNode (int parent, int firstAttribute, int previousSibling, int depth, XPathNodeType nodeType, string baseUri, bool isEmptyElement, string localName, string ns, string prefix, string value, string xmlLang, int namespaceNode, int lineNumber, int linePosition) + public void AddNode (int parent, int firstAttribute, int previousSibling, XPathNodeType nodeType, string baseUri, bool isEmptyElement, string localName, string ns, string prefix, string value, string xmlLang, int namespaceNode, int lineNumber, int linePosition) { if (nodes.Length < nodeIndex + 1) { nodeCapacity *= 4; @@ -224,7 +218,6 @@ namespace Mono.Xml.XPath nodes [nodeIndex].FirstAttribute = firstAttribute; nodes [nodeIndex].PreviousSibling = previousSibling; nodes [nodeIndex].NextSibling = 0; // dummy - nodes [nodeIndex].Depth = depth; nodes [nodeIndex].NodeType = nodeType; nodes [nodeIndex].BaseURI = baseUri; nodes [nodeIndex].IsEmptyElement = isEmptyElement; @@ -326,12 +319,13 @@ namespace Mono.Xml.XPath }
// When text after text, just add the value, and return.
- if (nodes [nodeIndex].Depth == writerDepth) {
+ if (nodes [nodeIndex].Parent == parentStack [parentStackIndex]) { switch (nodes [nodeIndex].NodeType) {
case XPathNodeType.Text:
case XPathNodeType.SignificantWhitespace:
- nodes [nodeIndex].Value += data;
- if (IsWhitespace (data))
+ string value = nodes [nodeIndex].Value + data; + nodes [nodeIndex].Value = value; + if (IsWhitespace (value)) nodes [nodeIndex].NodeType = XPathNodeType.SignificantWhitespace;
else
nodes [nodeIndex].NodeType = XPathNodeType.Text;
@@ -345,7 +339,6 @@ namespace Mono.Xml.XPath AddNode (parent, 0, // attribute prevSibling, - writerDepth, XPathNodeType.Text, null, false, @@ -384,7 +377,6 @@ namespace Mono.Xml.XPath AddNode (parent, 0, // attribute prevSibling, - writerDepth, XPathNodeType.Comment, null, false, @@ -408,7 +400,6 @@ namespace Mono.Xml.XPath AddNode (parent, 0, // attribute prevSibling, - writerDepth, XPathNodeType.ProcessingInstruction, null, false, @@ -432,7 +423,6 @@ namespace Mono.Xml.XPath AddNode (parent, 0, // attribute prevSibling, - writerDepth, XPathNodeType.Whitespace, null, false, @@ -489,7 +479,6 @@ namespace Mono.Xml.XPath AddNode (parent, 0, // dummy:firstAttribute previousSibling, - writerDepth, XPathNodeType.Element, null, false, @@ -505,8 +494,8 @@ namespace Mono.Xml.XPath private void PrepareStartElement (int previousSibling) { - firstAttributeIndex = 0; - lastNsIndexInCurrent = 0; + hasAttributes = false; + hasLocalNs = false; attrIndexAtStart = attributeIndex; nsIndexAtStart = nsIndex; @@ -536,13 +525,11 @@ namespace Mono.Xml.XPath default:
throw new InvalidOperationException ("Invalid state for writing EndElement: " + state);
}
- parentForFirstChild = -1;
+ parentStackIndex--; if (nodes [nodeIndex].NodeType == XPathNodeType.Element) {
if (!full)
nodes [nodeIndex].IsEmptyElement = true;
}
-
- writerDepth--;
}
public override void WriteStartAttribute (string prefix, string localName, string ns)
@@ -559,15 +546,15 @@ namespace Mono.Xml.XPath private void ProcessNamespace (string prefix, string ns) { - nsIndex++; + int nextTmp = hasLocalNs ? nsIndex : nodes [nodeIndex].FirstNamespace; - int nextTmp = lastNsIndexInCurrent == 0 ? nodes [nodeIndex].FirstNamespace : lastNsIndexInCurrent; + nsIndex++; this.AddNsNode (nodeIndex, prefix, ns, nextTmp); - lastNsIndexInCurrent = nsIndex; + hasLocalNs = true; openNamespace = true; } @@ -582,10 +569,10 @@ namespace Mono.Xml.XPath value, 0, 0); - if (firstAttributeIndex == 0) - firstAttributeIndex = attributeIndex; - else + if (hasAttributes) attributes [attributeIndex - 1].NextAttribute = attributeIndex; + else + hasAttributes = true; } public override void WriteEndAttribute ()
diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs index 86ddeb2ea5a..024584634e4 100644 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs @@ -44,7 +44,6 @@ namespace Mono.Xml.XPath class DTMXPathNavigator : XPathNavigator, IXmlLineInfo { -#region Copy of XPathDocument public DTMXPathNavigator (DTMXPathDocument document, XmlNameTable nameTable, DTMXPathLinkedNode [] nodes, @@ -57,7 +56,6 @@ namespace Mono.Xml.XPath this.namespaces = namespaces; this.idTable = idTable; this.nameTable = nameTable; - this.MoveToRoot (); this.document = document; } @@ -88,11 +86,6 @@ namespace Mono.Xml.XPath // ID table Hashtable idTable; -// // Key table (considered xsd:keyref for XPath 2.0) -// Hashtable keyRefTable; // [string key-name] -> idTable -// // idTable [string value] -> int nodeId -#endregion - bool currentIsNode; bool currentIsAttr; @@ -226,20 +219,32 @@ namespace Mono.Xml.XPath return nodes [currentNode].Value; } - // Element + // Element - collect all content values + int iter = nodes [currentNode].FirstChild; + if (iter == 0) + return String.Empty; + if (valueBuilder == null) valueBuilder = new StringBuilder (); else valueBuilder.Length = 0; - - int iter = nodes [currentNode].FirstChild; - int depth = nodes [currentNode].Depth; - while (iter < nodes.Length && nodes [iter].Depth > depth) { + + int end = nodes [currentNode].NextSibling; + if (end == 0) { + int tmp = currentNode; + do { + tmp = nodes [tmp].Parent; + end = nodes [tmp].NextSibling; + } while (end == 0 && tmp != 0); + if (end == 0) + end = nodes.Length; + } + + while (iter < end) { switch (nodes [iter].NodeType) { - case XPathNodeType.Comment: - case XPathNodeType.ProcessingInstruction: - break; - default: + case XPathNodeType.Text: + case XPathNodeType.SignificantWhitespace: + case XPathNodeType.Whitespace: valueBuilder.Append (nodes [iter].Value); break; } @@ -592,37 +597,9 @@ namespace Mono.Xml.XPath } #endregion - - /* - public string DebugDump { - get { - StringBuilder sb = new StringBuilder (); - - for (int i = 0; i < namespaces.Length; i++) { - DTMXPathNamespaceNode n = namespaces [i]; - sb.AppendFormat ("{0}: {1},{2} {3}/{4}\n", i, - n.DeclaredElement, n.NextNamespace, - n.Name, n.Namespace); - } - - for (int i=0; i<this.nodes.Length; i++) { - DTMXPathLinkedNode n = nodes [i]; - sb.AppendFormat ("{0}: {1}:{2} {3} {4} {5} {6} {7}\n", new object [] {i, n.Prefix, n.LocalName, n.NamespaceURI, n.FirstNamespace, n.FirstAttribute, n.FirstChild, n.Parent}); - } - - for (int i=0; i<this.attributes.Length; i++) { - DTMXPathAttributeNode n = attributes [i]; - sb.AppendFormat ("{0}: {1}:{2} {3} {4}\n", i, n.Prefix, n.LocalName, n.NamespaceURI, n.NextAttribute); - } - - return sb.ToString (); - } - } - */ - } - internal class XmlNamespaces + class XmlNamespaces { public const string XML = "http://www.w3.org/XML/1998/namespace"; public const string XMLNS = "http://www.w3.org/2000/xmlns/"; diff --git a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs index 9fdcf9e95a6..be368b07560 100644 --- a/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs +++ b/mcs/class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs @@ -53,7 +53,6 @@ namespace Mono.Xml.XPath public int NextSibling; public int FirstAttribute; public int FirstNamespace; - public int Depth; public XPathNodeType NodeType; public string BaseURI; public bool IsEmptyElement; |