You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
418
external/referencesource/System.Xml/System/Xml/Schema/Parser.cs
vendored
Normal file
418
external/referencesource/System.Xml/System/Xml/Schema/Parser.cs
vendored
Normal file
@ -0,0 +1,418 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="Parser.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Xml.Schema {
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal sealed partial class Parser {
|
||||
|
||||
SchemaType schemaType;
|
||||
XmlNameTable nameTable;
|
||||
SchemaNames schemaNames;
|
||||
ValidationEventHandler eventHandler;
|
||||
XmlNamespaceManager namespaceManager;
|
||||
XmlReader reader;
|
||||
PositionInfo positionInfo;
|
||||
bool isProcessNamespaces;
|
||||
int schemaXmlDepth = 0;
|
||||
int markupDepth;
|
||||
SchemaBuilder builder;
|
||||
XmlSchema schema;
|
||||
SchemaInfo xdrSchema;
|
||||
XmlResolver xmlResolver = null; //to be used only by XDRBuilder
|
||||
|
||||
//xs:Annotation perf fix
|
||||
XmlDocument dummyDocument;
|
||||
bool processMarkup;
|
||||
XmlNode parentNode;
|
||||
XmlNamespaceManager annotationNSManager;
|
||||
string xmlns;
|
||||
|
||||
//Whitespace check for text nodes
|
||||
XmlCharType xmlCharType = XmlCharType.Instance;
|
||||
|
||||
public Parser(SchemaType schemaType, XmlNameTable nameTable, SchemaNames schemaNames, ValidationEventHandler eventHandler) {
|
||||
this.schemaType = schemaType;
|
||||
this.nameTable = nameTable;
|
||||
this.schemaNames = schemaNames;
|
||||
this.eventHandler = eventHandler;
|
||||
this.xmlResolver = System.Xml.XmlConfiguration.XmlReaderSection.CreateDefaultResolver();
|
||||
processMarkup = true;
|
||||
dummyDocument = new XmlDocument();
|
||||
}
|
||||
|
||||
public SchemaType Parse(XmlReader reader, string targetNamespace) {
|
||||
StartParsing(reader, targetNamespace);
|
||||
while(ParseReaderNode() && reader.Read()) {}
|
||||
return FinishParsing();
|
||||
}
|
||||
|
||||
public void StartParsing(XmlReader reader, string targetNamespace) {
|
||||
this.reader = reader;
|
||||
positionInfo = PositionInfo.GetPositionInfo(reader);
|
||||
namespaceManager = reader.NamespaceManager;
|
||||
if (namespaceManager == null) {
|
||||
namespaceManager = new XmlNamespaceManager(nameTable);
|
||||
isProcessNamespaces = true;
|
||||
}
|
||||
else {
|
||||
isProcessNamespaces = false;
|
||||
}
|
||||
while (reader.NodeType != XmlNodeType.Element && reader.Read()) {}
|
||||
|
||||
markupDepth = int.MaxValue;
|
||||
schemaXmlDepth = reader.Depth;
|
||||
SchemaType rootType = schemaNames.SchemaTypeFromRoot(reader.LocalName, reader.NamespaceURI);
|
||||
|
||||
string code;
|
||||
if (!CheckSchemaRoot(rootType, out code)) {
|
||||
throw new XmlSchemaException(code, reader.BaseURI, positionInfo.LineNumber, positionInfo.LinePosition);
|
||||
}
|
||||
|
||||
if (schemaType == SchemaType.XSD) {
|
||||
schema = new XmlSchema();
|
||||
schema.BaseUri = new Uri(reader.BaseURI, UriKind.RelativeOrAbsolute);
|
||||
builder = new XsdBuilder(reader, namespaceManager, schema, nameTable, schemaNames, eventHandler);
|
||||
}
|
||||
else {
|
||||
Debug.Assert(schemaType == SchemaType.XDR);
|
||||
xdrSchema = new SchemaInfo();
|
||||
xdrSchema.SchemaType = SchemaType.XDR;
|
||||
builder = new XdrBuilder(reader, namespaceManager, xdrSchema, targetNamespace, nameTable, schemaNames, eventHandler);
|
||||
((XdrBuilder)builder).XmlResolver = xmlResolver;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckSchemaRoot(SchemaType rootType, out string code) {
|
||||
code = null;
|
||||
if (schemaType == SchemaType.None) {
|
||||
schemaType = rootType;
|
||||
}
|
||||
switch (rootType) {
|
||||
case SchemaType.XSD:
|
||||
if (schemaType != SchemaType.XSD) {
|
||||
code = Res.Sch_MixSchemaTypes;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SchemaType.XDR:
|
||||
if (schemaType == SchemaType.XSD) {
|
||||
code = Res.Sch_XSDSchemaOnly;
|
||||
return false;
|
||||
}
|
||||
else if (schemaType != SchemaType.XDR) {
|
||||
code = Res.Sch_MixSchemaTypes;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SchemaType.DTD: //Did not detect schema type that can be parsed by this parser
|
||||
case SchemaType.None:
|
||||
code = Res.Sch_SchemaRootExpected;
|
||||
if (schemaType == SchemaType.XSD) {
|
||||
code = Res.Sch_XSDSchemaRootExpected;
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public SchemaType FinishParsing() {
|
||||
return schemaType;
|
||||
}
|
||||
|
||||
public XmlSchema XmlSchema {
|
||||
get { return schema; }
|
||||
}
|
||||
|
||||
internal XmlResolver XmlResolver {
|
||||
set {
|
||||
xmlResolver = value;
|
||||
}
|
||||
}
|
||||
|
||||
public SchemaInfo XdrSchema {
|
||||
get { return xdrSchema; }
|
||||
}
|
||||
|
||||
public bool ParseReaderNode() {
|
||||
if (reader.Depth > markupDepth) {
|
||||
if (processMarkup) {
|
||||
ProcessAppInfoDocMarkup(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (reader.NodeType == XmlNodeType.Element) {
|
||||
if (builder.ProcessElement(reader.Prefix, reader.LocalName, reader.NamespaceURI)) {
|
||||
namespaceManager.PushScope();
|
||||
if (reader.MoveToFirstAttribute()) {
|
||||
do {
|
||||
builder.ProcessAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.Value);
|
||||
if (Ref.Equal(reader.NamespaceURI, schemaNames.NsXmlNs) && isProcessNamespaces) {
|
||||
namespaceManager.AddNamespace(reader.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value);
|
||||
}
|
||||
}
|
||||
while (reader.MoveToNextAttribute());
|
||||
reader.MoveToElement(); // get back to the element
|
||||
}
|
||||
builder.StartChildren();
|
||||
if (reader.IsEmptyElement) {
|
||||
namespaceManager.PopScope();
|
||||
builder.EndChildren();
|
||||
if (reader.Depth == schemaXmlDepth) {
|
||||
return false; // done
|
||||
}
|
||||
}
|
||||
else if (!builder.IsContentParsed()) { //AppInfo and Documentation
|
||||
markupDepth = reader.Depth;
|
||||
processMarkup = true;
|
||||
if (annotationNSManager == null) {
|
||||
annotationNSManager = new XmlNamespaceManager(nameTable);
|
||||
xmlns = nameTable.Add("xmlns");
|
||||
}
|
||||
ProcessAppInfoDocMarkup(true);
|
||||
}
|
||||
}
|
||||
else if (!reader.IsEmptyElement) { //UnsupportedElement in that context
|
||||
markupDepth = reader.Depth;
|
||||
processMarkup = false; //Hack to not process unsupported elements
|
||||
}
|
||||
}
|
||||
else if (reader.NodeType == XmlNodeType.Text) { //Check for whitespace
|
||||
if (!xmlCharType.IsOnlyWhitespace(reader.Value)) {
|
||||
builder.ProcessCData(reader.Value);
|
||||
}
|
||||
}
|
||||
else if (reader.NodeType == XmlNodeType.EntityReference ||
|
||||
reader.NodeType == XmlNodeType.SignificantWhitespace ||
|
||||
reader.NodeType == XmlNodeType.CDATA) {
|
||||
builder.ProcessCData(reader.Value);
|
||||
}
|
||||
else if (reader.NodeType == XmlNodeType.EndElement) {
|
||||
|
||||
if (reader.Depth == markupDepth) {
|
||||
if (processMarkup) {
|
||||
Debug.Assert(parentNode != null);
|
||||
XmlNodeList list = parentNode.ChildNodes;
|
||||
XmlNode[] markup = new XmlNode[list.Count];
|
||||
for (int i = 0; i < list.Count; i ++) {
|
||||
markup[i] = list[i];
|
||||
}
|
||||
builder.ProcessMarkup(markup);
|
||||
namespaceManager.PopScope();
|
||||
builder.EndChildren();
|
||||
}
|
||||
markupDepth = int.MaxValue;
|
||||
}
|
||||
else {
|
||||
namespaceManager.PopScope();
|
||||
builder.EndChildren();
|
||||
}
|
||||
if(reader.Depth == schemaXmlDepth) {
|
||||
return false; // done
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ProcessAppInfoDocMarkup(bool root) {
|
||||
//First time reader is positioned on AppInfo or Documentation element
|
||||
XmlNode currentNode = null;
|
||||
|
||||
switch (reader.NodeType) {
|
||||
case XmlNodeType.Element:
|
||||
annotationNSManager.PushScope();
|
||||
currentNode = LoadElementNode(root);
|
||||
// Dev10 (TFS) #479761: The following code was to address the issue of where an in-scope namespace delaration attribute
|
||||
// was not added when an element follows an empty element. This fix will result in persisting schema in a consistent form
|
||||
// although it does not change the semantic meaning of the schema.
|
||||
// Since it is as a breaking change and Dev10 needs to maintain the backward compatibility, this fix is being reverted.
|
||||
// if (reader.IsEmptyElement) {
|
||||
// annotationNSManager.PopScope();
|
||||
// }
|
||||
break;
|
||||
|
||||
case XmlNodeType.Text:
|
||||
currentNode = dummyDocument.CreateTextNode( reader.Value );
|
||||
goto default;
|
||||
|
||||
case XmlNodeType.SignificantWhitespace:
|
||||
currentNode = dummyDocument.CreateSignificantWhitespace( reader.Value );
|
||||
goto default;
|
||||
|
||||
case XmlNodeType.CDATA:
|
||||
currentNode = dummyDocument.CreateCDataSection( reader.Value );
|
||||
goto default;
|
||||
|
||||
case XmlNodeType.EntityReference:
|
||||
currentNode = dummyDocument.CreateEntityReference( reader.Name );
|
||||
goto default;
|
||||
|
||||
case XmlNodeType.Comment:
|
||||
currentNode = dummyDocument.CreateComment( reader.Value );
|
||||
goto default;
|
||||
|
||||
case XmlNodeType.ProcessingInstruction:
|
||||
currentNode = dummyDocument.CreateProcessingInstruction( reader.Name, reader.Value );
|
||||
goto default;
|
||||
|
||||
case XmlNodeType.EndEntity:
|
||||
break;
|
||||
|
||||
case XmlNodeType.Whitespace:
|
||||
break;
|
||||
|
||||
case XmlNodeType.EndElement:
|
||||
annotationNSManager.PopScope();
|
||||
parentNode = parentNode.ParentNode;
|
||||
break;
|
||||
|
||||
default: //other possible node types: Document/DocType/DocumentFrag/Entity/Notation/Xmldecl cannot appear as children of xs:appInfo or xs:doc
|
||||
Debug.Assert(currentNode != null);
|
||||
Debug.Assert(parentNode != null);
|
||||
parentNode.AppendChild(currentNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private XmlElement LoadElementNode(bool root) {
|
||||
Debug.Assert( reader.NodeType == XmlNodeType.Element );
|
||||
|
||||
XmlReader r = reader;
|
||||
bool fEmptyElement = r.IsEmptyElement;
|
||||
|
||||
XmlElement element = dummyDocument.CreateElement( r.Prefix, r.LocalName, r.NamespaceURI );
|
||||
element.IsEmpty = fEmptyElement;
|
||||
|
||||
if (root) {
|
||||
parentNode = element;
|
||||
}
|
||||
else {
|
||||
XmlAttributeCollection attributes = element.Attributes;
|
||||
if (r.MoveToFirstAttribute()) {
|
||||
do {
|
||||
if (Ref.Equal(r.NamespaceURI, schemaNames.NsXmlNs)) { //Namespace Attribute
|
||||
annotationNSManager.AddNamespace(r.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value);
|
||||
}
|
||||
XmlAttribute attr = LoadAttributeNode();
|
||||
attributes.Append( attr );
|
||||
} while(r.MoveToNextAttribute());
|
||||
}
|
||||
r.MoveToElement();
|
||||
string ns = annotationNSManager.LookupNamespace(r.Prefix);
|
||||
if (ns == null) {
|
||||
XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, namespaceManager.LookupNamespace(r.Prefix));
|
||||
attributes.Append(attr);
|
||||
}
|
||||
else if (ns.Length == 0) { //string.Empty prefix is mapped to string.Empty NS by default
|
||||
string elemNS = namespaceManager.LookupNamespace(r.Prefix);
|
||||
if (elemNS != string.Empty) {
|
||||
XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, elemNS);
|
||||
attributes.Append(attr);
|
||||
}
|
||||
}
|
||||
|
||||
while (r.MoveToNextAttribute()) {
|
||||
if (r.Prefix.Length != 0) {
|
||||
string attNS = annotationNSManager.LookupNamespace(r.Prefix);
|
||||
if (attNS == null) {
|
||||
XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, namespaceManager.LookupNamespace(r.Prefix));
|
||||
attributes.Append(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
r.MoveToElement();
|
||||
|
||||
parentNode.AppendChild(element);
|
||||
if (!r.IsEmptyElement) {
|
||||
parentNode = element;
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
private XmlAttribute CreateXmlNsAttribute(string prefix, string value) {
|
||||
XmlAttribute attr;
|
||||
if (prefix.Length == 0) {
|
||||
attr = dummyDocument.CreateAttribute(string.Empty, xmlns, XmlReservedNs.NsXmlNs);
|
||||
}
|
||||
else {
|
||||
attr = dummyDocument.CreateAttribute(xmlns, prefix, XmlReservedNs.NsXmlNs);
|
||||
}
|
||||
attr.AppendChild(dummyDocument.CreateTextNode(value));
|
||||
annotationNSManager.AddNamespace(prefix, value);
|
||||
return attr;
|
||||
}
|
||||
|
||||
private XmlAttribute LoadAttributeNode() {
|
||||
Debug.Assert(reader.NodeType == XmlNodeType.Attribute);
|
||||
|
||||
XmlReader r = reader;
|
||||
|
||||
XmlAttribute attr = dummyDocument.CreateAttribute(r.Prefix, r.LocalName, r.NamespaceURI);
|
||||
|
||||
while (r.ReadAttributeValue() ) {
|
||||
switch (r.NodeType) {
|
||||
case XmlNodeType.Text:
|
||||
attr.AppendChild(dummyDocument.CreateTextNode(r.Value));
|
||||
continue;
|
||||
case XmlNodeType.EntityReference:
|
||||
attr.AppendChild(LoadEntityReferenceInAttribute());
|
||||
continue;
|
||||
default:
|
||||
throw XmlLoader.UnexpectedNodeType( r.NodeType );
|
||||
}
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
private XmlEntityReference LoadEntityReferenceInAttribute() {
|
||||
Debug.Assert(reader.NodeType == XmlNodeType.EntityReference);
|
||||
|
||||
XmlEntityReference eref = dummyDocument.CreateEntityReference( reader.LocalName );
|
||||
if ( !reader.CanResolveEntity ) {
|
||||
return eref;
|
||||
}
|
||||
reader.ResolveEntity();
|
||||
|
||||
while (reader.ReadAttributeValue()) {
|
||||
switch (reader.NodeType) {
|
||||
case XmlNodeType.Text:
|
||||
eref.AppendChild(dummyDocument.CreateTextNode(reader.Value));
|
||||
continue;
|
||||
case XmlNodeType.EndEntity:
|
||||
if ( eref.ChildNodes.Count == 0 ) {
|
||||
eref.AppendChild(dummyDocument.CreateTextNode(String.Empty));
|
||||
}
|
||||
return eref;
|
||||
case XmlNodeType.EntityReference:
|
||||
eref.AppendChild(LoadEntityReferenceInAttribute());
|
||||
break;
|
||||
default:
|
||||
throw XmlLoader.UnexpectedNodeType( reader.NodeType );
|
||||
}
|
||||
}
|
||||
|
||||
return eref;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace System.Xml
|
Reference in New Issue
Block a user