<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0-preview.3.20214.6" />

XmlUtil

using System.Configuration.Internal; using System.Globalization; using System.IO; using System.Text; using System.Xml; namespace System.Configuration { internal sealed class XmlUtil : IDisposable, IConfigErrorInfo { private const int MaxLineWidth = 60; private static readonly int[] s_positionOffset = new int[18] { 0, 1, -1, 0, 9, 1, -1, 2, 4, -1, 10, -1, -1, 0, 0, 2, -1, 2 }; private StringWriter _cachedStringWriter; private int _lastLineNumber; private int _lastLinePosition; private Stream _stream; internal int TrueLinePosition => Reader.LinePosition - GetPositionOffset(Reader.NodeType); internal XmlTextReader Reader { get; set; } internal ConfigurationSchemaErrors SchemaErrors { get; } public string Filename { get; } public int LineNumber => Reader.LineNumber; internal XmlUtil(Stream stream, string name, bool readToFirstElement) : this(stream, name, readToFirstElement, new ConfigurationSchemaErrors()) { } internal XmlUtil(Stream stream, string name, bool readToFirstElement, ConfigurationSchemaErrors schemaErrors) { try { Filename = name; _stream = stream; Reader = new XmlTextReader(_stream) { XmlResolver = null }; SchemaErrors = schemaErrors; _lastLineNumber = 1; _lastLinePosition = 1; if (readToFirstElement) { Reader.WhitespaceHandling = WhitespaceHandling.None; bool flag = false; while (!flag && Reader.Read()) { switch (Reader.NodeType) { case XmlNodeType.Element: flag = true; break; default: throw new ConfigurationErrorsException(System.SR.Config_base_unrecognized_element, this); case XmlNodeType.Comment: case XmlNodeType.DocumentType: case XmlNodeType.XmlDeclaration: break; } } } } catch { ReleaseResources(); throw; } } public void Dispose() { ReleaseResources(); } private static int GetPositionOffset(XmlNodeType nodeType) { return s_positionOffset[(int)nodeType]; } private void ReleaseResources() { if (Reader != null) { Reader.Close(); Reader = null; } else _stream?.Close(); _stream = null; if (_cachedStringWriter != null) { _cachedStringWriter.Close(); _cachedStringWriter = null; } } internal void ReadToNextElement() { while (Reader.Read() && Reader.MoveToContent() != XmlNodeType.Element) { } } internal void SkipToNextElement() { Reader.Skip(); Reader.MoveToContent(); while (!Reader.EOF && Reader.NodeType != XmlNodeType.Element) { Reader.Read(); Reader.MoveToContent(); } } internal void StrictReadToNextElement(ExceptionAction action) { while (Reader.Read() && Reader.NodeType != XmlNodeType.Element) { VerifyIgnorableNodeType(action); } } internal void StrictSkipToNextElement(ExceptionAction action) { Reader.Skip(); while (!Reader.EOF && Reader.NodeType != XmlNodeType.Element) { VerifyIgnorableNodeType(action); Reader.Read(); } } internal void StrictSkipToOurParentsEndElement(ExceptionAction action) { int depth = Reader.Depth; while (Reader.Depth >= depth) { Reader.Skip(); } while (!Reader.EOF && Reader.NodeType != XmlNodeType.EndElement) { VerifyIgnorableNodeType(action); Reader.Read(); } } internal void VerifyIgnorableNodeType(ExceptionAction action) { XmlNodeType nodeType = Reader.NodeType; if (nodeType != XmlNodeType.Comment && nodeType != XmlNodeType.EndElement) { ConfigurationException ce = new ConfigurationErrorsException(System.SR.Config_base_unrecognized_element, this); SchemaErrors.AddError(ce, action); } } internal void VerifyNoUnrecognizedAttributes(ExceptionAction action) { if (Reader.MoveToNextAttribute()) AddErrorUnrecognizedAttribute(action); } internal bool VerifyRequiredAttribute(object requiredAttribute, string attrName, ExceptionAction action) { if (requiredAttribute == null) { AddErrorRequiredAttribute(attrName, action); return false; } return true; } internal void AddErrorUnrecognizedAttribute(ExceptionAction action) { ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Config_base_unrecognized_attribute, Reader.Name), this); SchemaErrors.AddError(ce, action); } internal void AddErrorRequiredAttribute(string attrib, ExceptionAction action) { ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Config_missing_required_attribute, attrib, Reader.Name), this); SchemaErrors.AddError(ce, action); } internal void AddErrorReservedAttribute(ExceptionAction action) { ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Config_reserved_attribute, Reader.Name), this); SchemaErrors.AddError(ce, action); } internal void AddErrorUnrecognizedElement(ExceptionAction action) { ConfigurationErrorsException ce = new ConfigurationErrorsException(System.SR.Config_base_unrecognized_element, this); SchemaErrors.AddError(ce, action); } internal void VerifyAndGetNonEmptyStringAttribute(ExceptionAction action, out string newValue) { if (!string.IsNullOrEmpty(Reader.Value)) newValue = Reader.Value; else { newValue = null; ConfigurationException ce = new ConfigurationErrorsException(System.SR.Format(System.SR.Empty_attribute, Reader.Name), this); SchemaErrors.AddError(ce, action); } } internal void VerifyAndGetBooleanAttribute(ExceptionAction action, bool defaultValue, out bool newValue) { switch (Reader.Value) { case "true": newValue = true; break; case "false": newValue = false; break; default: newValue = defaultValue; SchemaErrors.AddError(new ConfigurationErrorsException(System.SR.Format(System.SR.Config_invalid_boolean_attribute, Reader.Name), this), action); break; } } internal bool CopyOuterXmlToNextElement(XmlUtilWriter utilWriter, bool limitDepth) { CopyElement(utilWriter); return CopyReaderToNextElement(utilWriter, limitDepth); } internal bool SkipChildElementsAndCopyOuterXmlToNextElement(XmlUtilWriter utilWriter) { bool isEmptyElement = Reader.IsEmptyElement; int lineNumber = Reader.LineNumber; CopyXmlNode(utilWriter); if (!isEmptyElement) { while (Reader.NodeType != XmlNodeType.EndElement) { if (Reader.NodeType == XmlNodeType.Element) { Reader.Skip(); if (Reader.NodeType == XmlNodeType.Whitespace) Reader.Skip(); } else CopyXmlNode(utilWriter); } if (Reader.LineNumber != lineNumber) utilWriter.AppendSpacesToLinePosition(TrueLinePosition); CopyXmlNode(utilWriter); } return CopyReaderToNextElement(utilWriter, true); } internal bool CopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth) { bool flag = true; int num; if (limitDepth) { if (Reader.NodeType == XmlNodeType.EndElement) return true; num = Reader.Depth; } else num = 0; while (Reader.NodeType != XmlNodeType.Element && Reader.Depth >= num) { flag = CopyXmlNode(utilWriter); if (!flag) break; } return flag; } internal bool SkipAndCopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth) { if (!utilWriter.IsLastLineBlank) { Reader.Skip(); return CopyReaderToNextElement(utilWriter, limitDepth); } int num = limitDepth ? Reader.Depth : 0; Reader.Skip(); int lineNumber = Reader.LineNumber; while (!Reader.EOF) { if (Reader.NodeType != XmlNodeType.Whitespace) { if (Reader.LineNumber > lineNumber) { utilWriter.SeekToLineStart(); utilWriter.AppendWhiteSpace(lineNumber + 1, 1, LineNumber, TrueLinePosition); } break; } Reader.Read(); } while (!Reader.EOF && Reader.NodeType != XmlNodeType.Element && Reader.Depth >= num) { CopyXmlNode(utilWriter); } return !Reader.EOF; } private void CopyElement(XmlUtilWriter utilWriter) { int depth = Reader.Depth; bool isEmptyElement = Reader.IsEmptyElement; CopyXmlNode(utilWriter); while (Reader.Depth > depth) { CopyXmlNode(utilWriter); } if (!isEmptyElement) CopyXmlNode(utilWriter); } internal bool CopyXmlNode(XmlUtilWriter utilWriter) { string text = null; int fromLineNumber = -1; int fromLinePosition = -1; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; if (utilWriter.TrackPosition) { num = Reader.LineNumber; num2 = Reader.LinePosition; num3 = utilWriter.LineNumber; num4 = utilWriter.LinePosition; } switch (Reader.NodeType) { case XmlNodeType.Whitespace: utilWriter.Write(Reader.Value); break; case XmlNodeType.Element: text = (Reader.IsEmptyElement ? "/>" : ">"); fromLineNumber = Reader.LineNumber; fromLinePosition = Reader.LinePosition + Reader.Name.Length; utilWriter.Write('<'); utilWriter.Write(Reader.Name); while (Reader.MoveToNextAttribute()) { int lineNumber2 = Reader.LineNumber; int linePosition2 = Reader.LinePosition; utilWriter.AppendRequiredWhiteSpace(fromLineNumber, fromLinePosition, lineNumber2, linePosition2); int num7 = utilWriter.Write(Reader.Name); num7 += utilWriter.Write('='); num7 += utilWriter.AppendAttributeValue(Reader); fromLineNumber = lineNumber2; fromLinePosition = linePosition2 + num7; } break; case XmlNodeType.EndElement: text = ">"; fromLineNumber = Reader.LineNumber; fromLinePosition = Reader.LinePosition + Reader.Name.Length; utilWriter.Write("</"); utilWriter.Write(Reader.Name); break; case XmlNodeType.Comment: utilWriter.AppendComment(Reader.Value); break; case XmlNodeType.Text: utilWriter.AppendEscapeTextString(Reader.Value); break; case XmlNodeType.XmlDeclaration: text = "?>"; fromLineNumber = Reader.LineNumber; fromLinePosition = Reader.LinePosition + 3; utilWriter.Write("<?xml"); while (Reader.MoveToNextAttribute()) { int lineNumber = Reader.LineNumber; int linePosition = Reader.LinePosition; utilWriter.AppendRequiredWhiteSpace(fromLineNumber, fromLinePosition, lineNumber, linePosition); int num6 = utilWriter.Write(Reader.Name); num6 += utilWriter.Write('='); num6 += utilWriter.AppendAttributeValue(Reader); fromLineNumber = lineNumber; fromLinePosition = linePosition + num6; } Reader.MoveToElement(); break; case XmlNodeType.SignificantWhitespace: utilWriter.Write(Reader.Value); break; case XmlNodeType.ProcessingInstruction: utilWriter.AppendProcessingInstruction(Reader.Name, Reader.Value); break; case XmlNodeType.EntityReference: utilWriter.AppendEntityRef(Reader.Name); break; case XmlNodeType.CDATA: utilWriter.AppendCData(Reader.Value); break; case XmlNodeType.DocumentType: { int num5 = utilWriter.Write("<!DOCTYPE"); utilWriter.AppendRequiredWhiteSpace(_lastLineNumber, _lastLinePosition + num5, Reader.LineNumber, Reader.LinePosition); utilWriter.Write(Reader.Name); string text2 = null; if (Reader.HasValue) text2 = Reader.Value; fromLineNumber = Reader.LineNumber; fromLinePosition = Reader.LinePosition + Reader.Name.Length; if (Reader.MoveToFirstAttribute()) { utilWriter.AppendRequiredWhiteSpace(fromLineNumber, fromLinePosition, Reader.LineNumber, Reader.LinePosition); string name = Reader.Name; utilWriter.Write(name); utilWriter.AppendSpace(); utilWriter.AppendAttributeValue(Reader); Reader.MoveToAttribute(0); if (name == "PUBLIC") { Reader.MoveToAttribute(1); utilWriter.AppendSpace(); utilWriter.AppendAttributeValue(Reader); Reader.MoveToAttribute(1); } } if (!string.IsNullOrEmpty(text2)) { utilWriter.Write(" ["); utilWriter.Write(text2); utilWriter.Write(']'); } utilWriter.Write('>'); break; } } bool result = Reader.Read(); XmlNodeType nodeType = Reader.NodeType; if (text != null) { int positionOffset = GetPositionOffset(nodeType); int lineNumber3 = Reader.LineNumber; int toLinePosition = Reader.LinePosition - positionOffset - text.Length; utilWriter.AppendWhiteSpace(fromLineNumber, fromLinePosition, lineNumber3, toLinePosition); utilWriter.Write(text); } if (utilWriter.TrackPosition) { _lastLineNumber = num - num3 + utilWriter.LineNumber; if (num3 == utilWriter.LineNumber) _lastLinePosition = num2 - num4 + utilWriter.LinePosition; else _lastLinePosition = utilWriter.LinePosition; } return result; } private string RetrieveFullOpenElementTag() { StringBuilder stringBuilder = new StringBuilder(64); stringBuilder.Append('<'); stringBuilder.Append(Reader.Name); while (Reader.MoveToNextAttribute()) { stringBuilder.Append(' '); stringBuilder.Append(Reader.Name); stringBuilder.Append('='); stringBuilder.Append('"'); stringBuilder.Append(Reader.Value); stringBuilder.Append('"'); } stringBuilder.Append('>'); return stringBuilder.ToString(); } internal string UpdateStartElement(XmlUtilWriter utilWriter, string updatedStartElement, bool needsChildren, int linePosition, int indent) { string result = null; bool flag = false; string name = Reader.Name; if (Reader.IsEmptyElement) { if ((updatedStartElement == null) & needsChildren) updatedStartElement = RetrieveFullOpenElementTag(); flag = (updatedStartElement != null); } if (updatedStartElement == null) CopyXmlNode(utilWriter); else { string str = "</" + name + ">"; string xmlElement = updatedStartElement + str; string text = FormatXmlElement(xmlElement, linePosition, indent, true); int num = text.LastIndexOf('\n') + 1; string s; if (flag) { result = text.Substring(num); s = text.Substring(0, num); } else s = text.Substring(0, num - 2); utilWriter.Write(s); Reader.Read(); } return result; } private void ResetCachedStringWriter() { if (_cachedStringWriter == null) _cachedStringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture); else _cachedStringWriter.GetStringBuilder().Length = 0; } internal string CopySection() { ResetCachedStringWriter(); WhitespaceHandling whitespaceHandling = Reader.WhitespaceHandling; Reader.WhitespaceHandling = WhitespaceHandling.All; XmlUtilWriter xmlUtilWriter = new XmlUtilWriter(_cachedStringWriter, false); CopyElement(xmlUtilWriter); Reader.WhitespaceHandling = whitespaceHandling; if (whitespaceHandling == WhitespaceHandling.None && Reader.NodeType == XmlNodeType.Whitespace) Reader.Read(); xmlUtilWriter.Flush(); return ((StringWriter)xmlUtilWriter.Writer).ToString(); } internal static string FormatXmlElement(string xmlElement, int linePosition, int indent, bool skipFirstIndent) { XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.Unicode); XmlTextReader xmlTextReader = new XmlTextReader(xmlElement, XmlNodeType.Element, context); StringWriter writer = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture); XmlUtilWriter xmlUtilWriter = new XmlUtilWriter(writer, false); bool flag = false; bool flag2 = false; int num = 0; while (xmlTextReader.Read()) { XmlNodeType nodeType = xmlTextReader.NodeType; int num2; if (flag2) { xmlUtilWriter.Flush(); num2 = num - ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length; } else num2 = 0; switch (nodeType) { case XmlNodeType.Element: case XmlNodeType.CDATA: case XmlNodeType.Comment: case XmlNodeType.EndElement: if (!skipFirstIndent && !flag2) { xmlUtilWriter.AppendIndent(linePosition, indent, xmlTextReader.Depth, flag); if (flag) { xmlUtilWriter.Flush(); num = ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length; } } break; } flag2 = false; switch (nodeType) { case XmlNodeType.SignificantWhitespace: xmlUtilWriter.Write(xmlTextReader.Value); break; case XmlNodeType.CDATA: xmlUtilWriter.AppendCData(xmlTextReader.Value); break; case XmlNodeType.ProcessingInstruction: xmlUtilWriter.AppendProcessingInstruction(xmlTextReader.Name, xmlTextReader.Value); break; case XmlNodeType.Comment: xmlUtilWriter.AppendComment(xmlTextReader.Value); break; case XmlNodeType.Text: xmlUtilWriter.AppendEscapeTextString(xmlTextReader.Value); flag2 = true; break; case XmlNodeType.Element: { xmlUtilWriter.Write('<'); xmlUtilWriter.Write(xmlTextReader.Name); num2 += xmlTextReader.Name.Length + 2; int attributeCount = xmlTextReader.AttributeCount; for (int i = 0; i < attributeCount; i++) { bool flag3; if (num2 > 60) { xmlUtilWriter.AppendIndent(linePosition, indent, xmlTextReader.Depth - 1, true); num2 = indent; flag3 = false; xmlUtilWriter.Flush(); num = ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length; } else flag3 = true; xmlTextReader.MoveToNextAttribute(); xmlUtilWriter.Flush(); int length = ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length; if (flag3) xmlUtilWriter.AppendSpace(); xmlUtilWriter.Write(xmlTextReader.Name); xmlUtilWriter.Write('='); xmlUtilWriter.AppendAttributeValue(xmlTextReader); xmlUtilWriter.Flush(); num2 += ((StringWriter)xmlUtilWriter.Writer).GetStringBuilder().Length - length; } xmlTextReader.MoveToElement(); if (xmlTextReader.IsEmptyElement) xmlUtilWriter.Write(" />"); else xmlUtilWriter.Write('>'); break; } case XmlNodeType.EndElement: xmlUtilWriter.Write("</"); xmlUtilWriter.Write(xmlTextReader.Name); xmlUtilWriter.Write('>'); break; case XmlNodeType.EntityReference: xmlUtilWriter.AppendEntityRef(xmlTextReader.Name); break; } flag = true; skipFirstIndent = false; } xmlUtilWriter.Flush(); return ((StringWriter)xmlUtilWriter.Writer).ToString(); } } }