Indent text in xml serialization of string property?

后端 未结 1 1144
自闭症患者
自闭症患者 2020-12-19 15:00

I have a string property which will contain text with newlines. This text has some of the properties of HTML text in that whitespace is disregarded.

If I serialize t

相关标签:
1条回答
  • 2020-12-19 15:20

    I bumped into the same issue. At the end I came out with a custom writer:

    public class IndentTextXmlWriter : XmlTextWriter
    {
        private int indentLevel;
        private bool isInsideAttribute;
    
        public IndentTextXmlWriter(TextWriter textWriter): base(textWriter)
        {
        }
    
        public bool IndentText { get; set; }
    
        public override void WriteStartAttribute(string prefix, string localName, string ns)
        {
            isInsideAttribute = true;
            base.WriteStartAttribute(prefix, localName, ns);
        }
    
        public override void WriteEndAttribute()
        {
            isInsideAttribute = false;
            base.WriteEndAttribute();
        }
    
        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            indentLevel++;
            base.WriteStartElement(prefix, localName, ns);
        }
    
        public override void WriteEndElement()
        {
            indentLevel--;
            base.WriteEndElement();
        }
    
        public override void WriteString(string text)
        {
            if (String.IsNullOrEmpty(text) || isInsideAttribute || Formatting != Formatting.Indented || !IndentText || XmlSpace == XmlSpace.Preserve)
            {
                base.WriteString(text);
                return;
            }
    
            string[] lines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            string indent = new string(IndentChar, indentLevel * Indentation);
            foreach (string line in lines)
            {
                WriteRaw(Environment.NewLine);
                WriteRaw(indent);
                WriteRaw(line.Trim());
            }
    
            WriteRaw(Environment.NewLine);
            WriteRaw(new string(IndentChar, (indentLevel - 1) * Indentation));
        }
    }
    

    You can use it like this:

    [TestMethod]
    public void WriteIndentedText()
    {
        var result = new StringBuilder();
        using (var writer = new IndentTextXmlWriter(new StringWriter(result)){Formatting = Formatting.Indented, IndentText = true})
        {
            string text = @" Line 1
    Line 2
        Line 3  ";
            // some root
            writer.WriteStartDocument();
            writer.WriteStartElement("root");
            writer.WriteStartElement("child");
    
            // test auto-indenting
            writer.WriteStartElement("elementIndented");
            writer.WriteString(text);
            writer.WriteEndElement();
    
            // test space preserving
            writer.WriteStartElement("elementPreserved");
            writer.WriteAttributeString("xml", "space", null, "preserve");
            writer.WriteString(text);
    
            writer.WriteEndDocument();
        }
    
        Debug.WriteLine(result.ToString());
    }
    

    And the output:

    <?xml version="1.0" encoding="utf-16"?>
    <root>
      <child>
        <elementIndented>
          Line 1
          Line 2
          Line 3
        </elementIndented>
        <elementPreserved xml:space="preserve"> Line 1
    Line 2
        Line 3  </elementPreserved>
      </child>
    </root>
    
    0 讨论(0)
提交回复
热议问题