public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { var hasNewline = xmlReader.Value.Contains('\n'); if (elementProcessContext.Current.IsSignificantWhiteSpace && hasNewline) { elementProcessContext.Current.IsSignificantWhiteSpace = false; } if (hasNewline && !elementProcessContext.Current.IsPreservingSpace) { // For WhiteSpaces contain linefeed, trim all spaces/tab, // since the intent of this whitespace node is to break line, // and preserve the line feeds output.Append(xmlReader.Value.Replace(" ", "").Replace("\t", "").Replace("\r", "").Replace("\n", Environment.NewLine)); } else { // Preserve "pure" WhiteSpace between elements // e.g., // <TextBlock> // <Run>A</Run> <Run> // B // </Run> // </TextBlock> output.Append(xmlReader.Value.Replace("\n", Environment.NewLine)); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.SINGLE_LINE_TEXT_ONLY); var xmlEncodedContent = xmlReader.Value.ToXmlEncodedString(ignoreCarrier: true); if (elementProcessContext.Current.IsPreservingSpace) { output.Append(xmlEncodedContent.Replace("\n", Environment.NewLine)); } else { string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); IEnumerable <string> textLines = xmlEncodedContent.Trim().Split('\n').Where(x => x.Trim().Length > 0).ToList(); foreach (var line in textLines) { var trimmedLine = line.Trim(); if (trimmedLine.Length > 0) { output.Append(Environment.NewLine).Append(currentIndentString).Append(trimmedLine); } } } if (xmlEncodedContent.Any(x => x == '\n')) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MULTI_LINE_TEXT_ONLY); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { var hasNewline = xmlReader.Value.Contains('\n'); if (elementProcessContext.Current.IsSignificantWhiteSpace && hasNewline) elementProcessContext.Current.IsSignificantWhiteSpace = false; if (hasNewline && !elementProcessContext.Current.IsPreservingSpace) { // For WhiteSpaces contain linefeed, trim all spaces/tab, // since the intent of this whitespace node is to break line, // and preserve the line feeds output.Append(xmlReader.Value.Replace(" ", "").Replace("\t", "").Replace("\r", "").Replace("\n", Environment.NewLine)); } else { // Preserve "pure" WhiteSpace between elements // e.g., // <TextBlock> // <Run>A</Run> <Run> // B // </Run> // </TextBlock> output.Append(xmlReader.Value.Replace("\n", Environment.NewLine)); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.SINGLE_LINE_TEXT_ONLY); var xmlEncodedContent = xmlReader.Value.ToXmlEncodedString(ignoreCarrier: true); if (elementProcessContext.Current.IsPreservingSpace) { output.Append(xmlEncodedContent.Replace("\n", Environment.NewLine)); } else { string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); IEnumerable<string> textLines = xmlEncodedContent.Trim().Split('\n').Where(x => x.Trim().Length > 0).ToList(); foreach (var line in textLines) { var trimmedLine = line.Trim(); if (trimmedLine.Length > 0) { output.Append(Environment.NewLine).Append(currentIndentString).Append(trimmedLine); } } } if (xmlEncodedContent.Any(x => x == '\n')) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MULTI_LINE_TEXT_ONLY); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MIXED); string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); string content = xmlReader.Value; if (output.Length > 0 && !output.IsNewLine()) { output.Append(Environment.NewLine); } if (content.Contains("<") && content.Contains(">")) { output.Append(currentIndentString); output.Append("<!--"); if (content.Contains("\n")) { output.Append(string.Join(Environment.NewLine, content.GetLines().Select(x => x.TrimEnd(' ')))); if (content.TrimEnd(' ').EndsWith("\n")) { output.Append(currentIndentString); } } else { output.Append(content); } output.Append("-->"); } else if (content.Contains("#region") || content.Contains("#endregion")) { output.Append(currentIndentString).Append("<!--").Append(content.Trim()).Append("-->"); } else if (content.Contains("\n")) { output.Append(currentIndentString).Append("<!--"); var contentIndentString = _indentService.GetIndentString(xmlReader.Depth + 1); foreach (var line in content.Trim().GetLines()) { output.Append(Environment.NewLine).Append(contentIndentString).Append(line.Trim()); } output.Append(Environment.NewLine).Append(currentIndentString).Append("-->"); } else { output .Append(currentIndentString) .Append("<!--") .Append(' ', _options.CommentSpaces) .Append(content.Trim()) .Append(' ', _options.CommentSpaces).Append("-->"); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MIXED); string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); string content = xmlReader.Value; if (output.Length > 0 && !output.IsNewLine()) { output.Append(Environment.NewLine); } if (content.Contains("<") && content.Contains(">")) { output.Append(currentIndentString); output.Append("<!--"); if (content.Contains("\n")) { output.Append(string.Join(Environment.NewLine, content.GetLines().Select(x => x.TrimEnd(' ')))); if (content.TrimEnd(' ').EndsWith("\n")) { output.Append(currentIndentString); } } else output.Append(content); output.Append("-->"); } else if (content.Contains("#region") || content.Contains("#endregion")) { output.Append(currentIndentString).Append("<!--").Append(content.Trim()).Append("-->"); } else if (content.Contains("\n")) { output.Append(currentIndentString).Append("<!--"); var contentIndentString = _indentService.GetIndentString(xmlReader.Depth + 1); foreach (var line in content.Trim().GetLines()) { output.Append(Environment.NewLine).Append(contentIndentString).Append(line.Trim()); } output.Append(Environment.NewLine).Append(currentIndentString).Append("-->"); } else { output .Append(currentIndentString) .Append("<!--") .Append(' ', _options.CommentSpaces) .Append(content.Trim()) .Append(' ', _options.CommentSpaces).Append("-->"); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MIXED); string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); if (!output.IsNewLine()) { output.Append(Environment.NewLine); } output.Append(currentIndentString).Append("<?Mapping ").Append(xmlReader.Value).Append(" ?>"); }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { if (elementProcessContext.Current.IsPreservingSpace) { output.Append("</").Append(xmlReader.Name).Append(">"); } else if (elementProcessContext.Current.IsSignificantWhiteSpace && !output.IsNewLine()) { output.Append("</").Append(xmlReader.Name).Append(">"); } // Shrink the current element, if it has no content. // E.g., <Element> </Element> => <Element /> else if (elementProcessContext.Current.ContentType == ContentTypeEnum.NONE && _options.RemoveEndingTagOfEmptyElement) { #region shrink element with no content output = output.TrimEnd(' ', '\t', '\r', '\n'); int bracketIndex = output.LastIndexOf('>'); output.Insert(bracketIndex, '/'); if (output[bracketIndex - 1] != '\t' && output[bracketIndex - 1] != ' ' && _options.SpaceBeforeClosingSlash) { output.Insert(bracketIndex, ' '); } #endregion shrink element with no content } else if (elementProcessContext.Current.ContentType == ContentTypeEnum.SINGLE_LINE_TEXT_ONLY && elementProcessContext.Current.IsMultlineStartTag == false) { int bracketIndex = output.LastIndexOf('>'); string text = output.Substring(bracketIndex + 1, output.Length - bracketIndex - 1).Trim(); output.Length = bracketIndex + 1; output.Append(text).Append("</").Append(xmlReader.Name).Append(">"); } else { string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); if (!output.IsNewLine()) { output.Append(Environment.NewLine); } output.Append(currentIndentString).Append("</").Append(xmlReader.Name).Append(">"); } elementProcessContext.Pop(); }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { // If there is linefeed(s) between element and CDATA then treat CDATA as element and indent accordingly, otherwise treat as single line text if (output.IsNewLine()) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MULTI_LINE_TEXT_ONLY); if (!elementProcessContext.Current.IsPreservingSpace) { string currentIndentString = _indentService.GetIndentString(xmlReader.Depth); output.Append(currentIndentString); } } else { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.SINGLE_LINE_TEXT_ONLY); } output.Append("<![CDATA[") // All newlines are returned by XmlReader as \n due to requirements in the XML Specification (http://www.w3.org/TR/2008/REC-xml-20081126/#sec-line-ends) // Change them back into the environment newline characters. .Append(xmlReader.Value.Replace("\n", Environment.NewLine)).Append("]]>"); }
private void ProcessAttributes(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext, bool isNoLineBreakElement, string attributeIndentationString) { var list = new List <AttributeInfo>(xmlReader.AttributeCount); while (xmlReader.MoveToNextAttribute()) { list.Add(_attributeInfoFactory.Create(xmlReader)); // Check for xml:space as defined in http://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space if (xmlReader.IsXmlSpaceAttribute()) { elementProcessContext.Current.IsPreservingSpace = (xmlReader.Value == "preserve"); } } if (_options.EnableAttributeReordering) { list.Sort(AttributeInfoComparison); } var noLineBreakInAttributes = (list.Count <= _options.AttributesTolerance) || isNoLineBreakElement; var forceLineBreakInAttributes = false; // Root element? if (elementProcessContext.Count == 2) { switch (_options.RootElementLineBreakRule) { case LineBreakRule.Default: break; case LineBreakRule.Always: noLineBreakInAttributes = false; forceLineBreakInAttributes = true; break; case LineBreakRule.Never: noLineBreakInAttributes = true; break; default: throw new ArgumentOutOfRangeException(); } } // No need to break attributes if (noLineBreakInAttributes) { foreach (var attrInfo in list) { output .Append(' ') .Append(_attributeInfoFormatter.ToSingleLineString(attrInfo)); } elementProcessContext.Current.IsMultlineStartTag = false; } // Need to break attributes else { var attributeLines = new List <string>(); var currentLineBuffer = new StringBuilder(); int attributeCountInCurrentLineBuffer = 0; AttributeInfo lastAttributeInfo = null; foreach (AttributeInfo attrInfo in list) { // Attributes with markup extension, always put on new line if (attrInfo.IsMarkupExtension && _options.FormatMarkupExtension) { if (currentLineBuffer.Length > 0) { attributeLines.Add(currentLineBuffer.ToString()); currentLineBuffer.Length = 0; attributeCountInCurrentLineBuffer = 0; } attributeLines.Add(_attributeInfoFormatter.ToMultiLineString(attrInfo, attributeIndentationString)); } else { string pendingAppend = _attributeInfoFormatter.ToSingleLineString(attrInfo); bool isAttributeCharLengthExceeded = (attributeCountInCurrentLineBuffer > 0 && _options.MaxAttributeCharatersPerLine > 0 && currentLineBuffer.Length + pendingAppend.Length > _options.MaxAttributeCharatersPerLine); bool isAttributeCountExceeded = (_options.MaxAttributesPerLine > 0 && attributeCountInCurrentLineBuffer + 1 > _options.MaxAttributesPerLine); bool isAttributeRuleGroupChanged = _options.PutAttributeOrderRuleGroupsOnSeparateLines && lastAttributeInfo != null && lastAttributeInfo.OrderRule.Group != attrInfo.OrderRule.Group; if (currentLineBuffer.Length > 0 && (forceLineBreakInAttributes || isAttributeCharLengthExceeded || isAttributeCountExceeded || isAttributeRuleGroupChanged)) { attributeLines.Add(currentLineBuffer.ToString()); currentLineBuffer.Length = 0; attributeCountInCurrentLineBuffer = 0; } currentLineBuffer.AppendFormat("{0} ", pendingAppend); attributeCountInCurrentLineBuffer++; } lastAttributeInfo = attrInfo; } if (currentLineBuffer.Length > 0) { attributeLines.Add(currentLineBuffer.ToString()); } for (int i = 0; i < attributeLines.Count; i++) { // Put first attribute line on same line as element? if (0 == i && _options.KeepFirstAttributeOnSameLine) { output .Append(' ') .Append(attributeLines[i].Trim()); } else { output .Append(Environment.NewLine) .Append(_indentService.Normalize(attributeIndentationString + attributeLines[i].Trim())); } } elementProcessContext.Current.IsMultlineStartTag = true; } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { // All newlines are returned by XmlReader as \n due to requirements in the XML Specification (http://www.w3.org/TR/2008/REC-xml-20081126/#sec-line-ends) // Change them back into the environment newline characters. output.Append(xmlReader.Value.Replace("\n", Environment.NewLine)); }
private string Format(string xamlSource) { StringBuilder output = new StringBuilder(); using (var sourceReader = new StringReader(xamlSource)) { using (XmlReader xmlReader = XmlReader.Create(sourceReader)) { var elementProcessContext = new ElementProcessContext(); while (xmlReader.Read()) { IDocumentProcessor processor; if (_documentProcessors.TryGetValue(xmlReader.NodeType, out processor)) { processor.Process(xmlReader, output, elementProcessContext); } else { Trace.WriteLine($"Unprocessed NodeType: {xmlReader.NodeType} Name: {xmlReader.Name} Value: {xmlReader.Value}"); } } } } return output.ToString(); }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { output.Append("<?xml "); output.Append(xmlReader.Value.Trim()); output.Append(" ?>"); }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MIXED); var elementName = xmlReader.Name; elementProcessContext.Push( new ElementProcessStatus { Parent = elementProcessContext.Current, Name = elementName, ContentType = ContentTypeEnum.NONE, IsMultlineStartTag = false, IsPreservingSpace = elementProcessContext.Current.IsPreservingSpace } ); var currentIndentString = _indentService.GetIndentString(xmlReader.Depth); var attributeIndetationString = GetAttributeIndetationString(xmlReader); // Calculate how element should be indented if (!elementProcessContext.Current.IsPreservingSpace) { // "Run" get special treatment to try to preserve spacing. Use xml:space='preserve' to make sure! if (elementName.Equals("Run")) { elementProcessContext.Current.Parent.IsSignificantWhiteSpace = true; if (output.Length == 0 || output.IsNewLine()) { output.Append(currentIndentString); } } else { elementProcessContext.Current.Parent.IsSignificantWhiteSpace = false; if (output.Length == 0 || output.IsNewLine()) { output.Append(currentIndentString); } else { output .Append(Environment.NewLine) .Append(currentIndentString); } } } // Output the element itself output .Append('<') .Append(elementName); bool isEmptyElement = xmlReader.IsEmptyElement; if (xmlReader.HasAttributes) { bool isNoLineBreakElement = IsNoLineBreakElement(elementName); ProcessAttributes(xmlReader, output, elementProcessContext, isNoLineBreakElement, attributeIndetationString); } // Determine if to put ending bracket on new line bool putEndingBracketOnNewLine = (_options.PutEndingBracketOnNewLine && elementProcessContext.Current.IsMultlineStartTag); if (putEndingBracketOnNewLine) { // Indent ending bracket just like an attribute output .Append(Environment.NewLine) .Append(attributeIndetationString); } if (isEmptyElement) { if (putEndingBracketOnNewLine == false && _options.SpaceBeforeClosingSlash) { output.Append(' '); } output.Append("/>"); // Self closing element. Remember to pop element context. elementProcessContext.Pop(); } else { output.Append(">"); } }
public void Process(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext) { elementProcessContext.UpdateParentElementProcessStatus(ContentTypeEnum.MIXED); var elementName = xmlReader.Name; elementProcessContext.Push( new ElementProcessStatus { Parent = elementProcessContext.Current, Name = elementName, ContentType = ContentTypeEnum.NONE, IsMultlineStartTag = false, IsPreservingSpace = elementProcessContext.Current.IsPreservingSpace } ); var currentIndentString = _indentService.GetIndentString(xmlReader.Depth); var attributeIndetationString = GetAttributeIndetationString(xmlReader); // Calculate how element should be indented if (!elementProcessContext.Current.IsPreservingSpace) { // "Run" get special treatment to try to preserve spacing. Use xml:space='preserve' to make sure! if (elementName.Equals("Run")) { elementProcessContext.Current.Parent.IsSignificantWhiteSpace = true; if (output.Length == 0 || output.IsNewLine()) { output.Append(currentIndentString); } } else { elementProcessContext.Current.Parent.IsSignificantWhiteSpace = false; if (output.Length == 0 || output.IsNewLine()) { output.Append(currentIndentString); } else { output .Append(Environment.NewLine) .Append(currentIndentString); } } } // Output the element itself output .Append('<') .Append(elementName); bool isEmptyElement = xmlReader.IsEmptyElement; if (xmlReader.HasAttributes) { bool isNoLineBreakElement = IsNoLineBreakElement(elementName); ProcessAttributes(xmlReader, output, elementProcessContext, isNoLineBreakElement, attributeIndetationString); } // Determine if to put ending bracket on new line bool putEndingBracketOnNewLine = (_options.PutEndingBracketOnNewLine && elementProcessContext.Current.IsMultlineStartTag); if(putEndingBracketOnNewLine) { // Indent ending bracket just like an attribute output .Append(Environment.NewLine) .Append(attributeIndetationString); } if (isEmptyElement) { if (putEndingBracketOnNewLine == false && _options.SpaceBeforeClosingSlash) { output.Append(' '); } output.Append("/>"); // Self closing element. Remember to pop element context. elementProcessContext.Pop(); } else { output.Append(">"); } }
private void ProcessAttributes(XmlReader xmlReader, StringBuilder output, ElementProcessContext elementProcessContext, bool isNoLineBreakElement, string attributeIndentationString) { var list = new List<AttributeInfo>(xmlReader.AttributeCount); while (xmlReader.MoveToNextAttribute()) { list.Add(_attributeInfoFactory.Create(xmlReader)); // Check for xml:space as defined in http://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space if (xmlReader.IsXmlSpaceAttribute()) { elementProcessContext.Current.IsPreservingSpace = (xmlReader.Value == "preserve"); } } if (_options.EnableAttributeReordering) list.Sort(AttributeInfoComparison); var noLineBreakInAttributes = (list.Count <= _options.AttributesTolerance) || isNoLineBreakElement; var forceLineBreakInAttributes = false; // Root element? if (elementProcessContext.Count == 2) { switch (_options.RootElementLineBreakRule) { case LineBreakRule.Default: break; case LineBreakRule.Always: noLineBreakInAttributes = false; forceLineBreakInAttributes = true; break; case LineBreakRule.Never: noLineBreakInAttributes = true; break; default: throw new ArgumentOutOfRangeException(); } } // No need to break attributes if (noLineBreakInAttributes) { foreach (var attrInfo in list) { output .Append(' ') .Append(_attributeInfoFormatter.ToSingleLineString(attrInfo)); } elementProcessContext.Current.IsMultlineStartTag = false; } // Need to break attributes else { var attributeLines = new List<string>(); var currentLineBuffer = new StringBuilder(); int attributeCountInCurrentLineBuffer = 0; AttributeInfo lastAttributeInfo = null; foreach (AttributeInfo attrInfo in list) { // Attributes with markup extension, always put on new line if (attrInfo.IsMarkupExtension && _options.FormatMarkupExtension) { if (currentLineBuffer.Length > 0) { attributeLines.Add(currentLineBuffer.ToString()); currentLineBuffer.Length = 0; attributeCountInCurrentLineBuffer = 0; } attributeLines.Add(_attributeInfoFormatter.ToMultiLineString(attrInfo, attributeIndentationString)); } else { string pendingAppend = _attributeInfoFormatter.ToSingleLineString(attrInfo); bool isAttributeCharLengthExceeded = (attributeCountInCurrentLineBuffer > 0 && _options.MaxAttributeCharatersPerLine > 0 && currentLineBuffer.Length + pendingAppend.Length > _options.MaxAttributeCharatersPerLine); bool isAttributeCountExceeded = (_options.MaxAttributesPerLine > 0 && attributeCountInCurrentLineBuffer + 1 > _options.MaxAttributesPerLine); bool isAttributeRuleGroupChanged = _options.PutAttributeOrderRuleGroupsOnSeparateLines && lastAttributeInfo != null && lastAttributeInfo.OrderRule.Group != attrInfo.OrderRule.Group; if (currentLineBuffer.Length > 0 && (forceLineBreakInAttributes || isAttributeCharLengthExceeded || isAttributeCountExceeded || isAttributeRuleGroupChanged)) { attributeLines.Add(currentLineBuffer.ToString()); currentLineBuffer.Length = 0; attributeCountInCurrentLineBuffer = 0; } currentLineBuffer.AppendFormat("{0} ", pendingAppend); attributeCountInCurrentLineBuffer++; } lastAttributeInfo = attrInfo; } if (currentLineBuffer.Length > 0) { attributeLines.Add(currentLineBuffer.ToString()); } for (int i = 0; i < attributeLines.Count; i++) { // Put first attribute line on same line as element? if (0 == i && _options.KeepFirstAttributeOnSameLine) { output .Append(' ') .Append(attributeLines[i].Trim()); } else { output .Append(Environment.NewLine) .Append(_indentService.Normalize(attributeIndentationString + attributeLines[i].Trim())); } } elementProcessContext.Current.IsMultlineStartTag = true; } }