C# 反序列化(xmlTextReader); } } 公共字符串规范化(字符串值) { if(System.String.IsNullOrEmpty(value)==false) { value=value.Replace('\u0009',''); 值=值。替换('\u000a',''); 值=值。替换('\u000d',''); } 返回值; } 公共对象[]XmlTextReaderCases= { 新对象[]{false,WhitespaceHandling.All}, 新对象[]{false,WhitespaceHandling.None}, 新对象[]{false,WhitespaceHandling.signific}, 新对象[]{true,WhitespaceHandling.All}, 新对象[]{true,WhitespaceHandling.None}, 新对象[]{true,WhitespaceHandling.signific}, }; [测试] [TestCaseSource(“XmlTextReaderCases”)] 应替换公共空白区域(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.carinereturns,Is.EqualTo(“returns”)); } [测试] [TestCaseSource(“XmlTextReaderCases”)] 应替换公共无效换行符(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.Newlines,Is.EqualTo(“Newlines-Newlines”)); } [测试] [TestCaseSource(“XmlTextReaderCases”)] 公共空格应保持不变(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.Spaces,Is.EqualTo(“Spaces”)); } [测试] [TestCaseSource(“XmlTextReaderCases”)] 应替换公共无效选项卡(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.Tabs,Is.EqualTo(“Tabs”)); } } }

C# 反序列化(xmlTextReader); } } 公共字符串规范化(字符串值) { if(System.String.IsNullOrEmpty(value)==false) { value=value.Replace('\u0009',''); 值=值。替换('\u000a',''); 值=值。替换('\u000d',''); } 返回值; } 公共对象[]XmlTextReaderCases= { 新对象[]{false,WhitespaceHandling.All}, 新对象[]{false,WhitespaceHandling.None}, 新对象[]{false,WhitespaceHandling.signific}, 新对象[]{true,WhitespaceHandling.All}, 新对象[]{true,WhitespaceHandling.None}, 新对象[]{true,WhitespaceHandling.signific}, }; [测试] [TestCaseSource(“XmlTextReaderCases”)] 应替换公共空白区域(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.carinereturns,Is.EqualTo(“returns”)); } [测试] [TestCaseSource(“XmlTextReaderCases”)] 应替换公共无效换行符(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.Newlines,Is.EqualTo(“Newlines-Newlines”)); } [测试] [TestCaseSource(“XmlTextReaderCases”)] 公共空格应保持不变(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.Spaces,Is.EqualTo(“Spaces”)); } [测试] [TestCaseSource(“XmlTextReaderCases”)] 应替换公共无效选项卡(布尔规范化、空格处理、空格处理) { 设置(规范化、空白处理); Assert.That(root.Tabs,Is.EqualTo(“Tabs”)); } } },c#,.net,xml,C#,.net,Xml,请注意,XmlSerializer实际上用换行符(\u000a)替换了回车符(\u000d),因此它在反序列化XML时进行了一些基本的规范化 ==== 编辑以使问题完全清楚: 问:有人能告诉我如何设置下面的XmlSerializer类,以便所有替换测试都能通过吗?尝试以下方法: using NUnit.Framework; using System.IO; using System.Xml; using System.Xml.Serialization; namespace Deseriali

请注意,XmlSerializer实际上用换行符(\u000a)替换了回车符(\u000d),因此它在反序列化XML时进行了一些基本的规范化

====

编辑以使问题完全清楚:


问:有人能告诉我如何设置下面的XmlSerializer类,以便所有替换测试都能通过吗?

尝试以下方法:

using NUnit.Framework;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace Deserialize.Tests
{
    [XmlRoot("Root")]
    public class Root
    {
        [XmlElement(DataType = "normalizedString")]
        public string CarriageReturns;

        [XmlElement(DataType = "normalizedString")]
        public string Newlines;

        [XmlElement(DataType = "normalizedString")]
        public string Spaces;

        [XmlElement(DataType = "normalizedString")]
        public string Tabs;
    }

    [TestFixture]
    public class DeserializeTests
    {
        private const string xml = "<Root>" +
            "<CarriageReturns> returns\u000d\u000dreturns </CarriageReturns>" +
            "<Newlines> newlines\u000a\u000anewlines </Newlines>" +
            "<Spaces> spaces  spaces </Spaces>" +
            "<Tabs> tabs\t\ttabs </Tabs>" +
            "</Root>";

        private Root root;

        public void SetUp(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            //MemoryStream_SetUp(normalization, whitespaceHandling);
            //StringReader_SetUp(normalization, whitespaceHandling);
            //XmlDocument_SetUp(normalization, whitespaceHandling);
            XmlTextReader_SetUp(normalization, whitespaceHandling);
        }

        public void MemoryStream_SetUp(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            using (var memoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xml)))
            {
                var serializer = new XmlSerializer(typeof(Root));
                root = (Root)serializer.Deserialize(memoryStream);
            }
        }

        public void StringReader_SetUp(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            using (var stringReader = new StringReader(xml))
            using (var xmlTextReader = new XmlTextReader(stringReader))
            {
                xmlTextReader.Normalization = normalization;
                xmlTextReader.WhitespaceHandling = whitespaceHandling;

                var serializer = new XmlSerializer(typeof(Root));
                root = (Root)serializer.Deserialize(xmlTextReader);
            }
        }

        public void XmlDocument_SetUp(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            var doc = new XmlDocument();
            doc.PreserveWhitespace = false;
            doc.LoadXml(xml);
            root = new Root()
            {
                //CarriageReturns = Normalize(doc.DocumentElement.SelectSingleNode("/Root/CarriageReturns").InnerText),
                //Newlines = Normalize(doc.DocumentElement.SelectSingleNode("/Root/Newlines").InnerText),
                //Spaces = Normalize(doc.DocumentElement.SelectSingleNode("/Root/Spaces").InnerText),
                //Tabs = Normalize(doc.DocumentElement.SelectSingleNode("/Root/Tabs").InnerText),

                CarriageReturns = doc.DocumentElement.SelectSingleNode("/Root/CarriageReturns").InnerText,
                Newlines = doc.DocumentElement.SelectSingleNode("/Root/Newlines").InnerText,
                Spaces = doc.DocumentElement.SelectSingleNode("/Root/Spaces").InnerText,
                Tabs = doc.DocumentElement.SelectSingleNode("/Root/Tabs").InnerText,
            };
        }

        public void XmlTextReader_SetUp(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            using (var memoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xml)))
            using (var xmlTextReader = new XmlTextReader(memoryStream))
            {
                xmlTextReader.Normalization = normalization;
                xmlTextReader.WhitespaceHandling = whitespaceHandling;

                var serializer = new XmlSerializer(typeof(Root));
                root = (Root)serializer.Deserialize(xmlTextReader);
            }
        }

        public string Normalize(string value)
        {
            if (System.String.IsNullOrEmpty(value) == false)
            {
                value = value.Replace('\u0009', ' ');
                value = value.Replace('\u000a', ' ');
                value = value.Replace('\u000d', ' ');
            }
            return value;
        }

        public object[] XmlTextReaderCases =
        {
            new object[] { false, WhitespaceHandling.All },
            new object[] { false, WhitespaceHandling.None },
            new object[] { false, WhitespaceHandling.Significant },
            new object[] { true, WhitespaceHandling.All },
            new object[] { true, WhitespaceHandling.None },
            new object[] { true, WhitespaceHandling.Significant },
        };

        [Test]
        [TestCaseSource("XmlTextReaderCases")]
        public void CarriageReturns_should_be_replaced(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            SetUp(normalization, whitespaceHandling);
            Assert.That(root.CarriageReturns, Is.EqualTo(" returns  returns "));
        }

        [Test]
        [TestCaseSource("XmlTextReaderCases")]
        public void Newlines_should_be_replaced(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            SetUp(normalization, whitespaceHandling);
            Assert.That(root.Newlines, Is.EqualTo(" newlines  newlines "));
        }

        [Test]
        [TestCaseSource("XmlTextReaderCases")]
        public void Spaces_should_be_unchanged(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            SetUp(normalization, whitespaceHandling);
            Assert.That(root.Spaces, Is.EqualTo(" spaces  spaces "));
        }

        [Test]
        [TestCaseSource("XmlTextReaderCases")]
        public void Tabs_should_be_replaced(bool normalization, WhitespaceHandling whitespaceHandling)
        {
            SetUp(normalization, whitespaceHandling);
            Assert.That(root.Tabs, Is.EqualTo(" tabs  tabs "));
        }
    }
}
   public class Root
    {
        private string _CarriageReturns { get; set; }
        private string _Newlines { get; set; }
        private string _Spaces { get; set; }
        private string _Tabs { get; set; }

        [XmlElement(DataType = "normalizedString")]
        public string CarriageReturns
        {
            get { return _CarriageReturns; }
            set { _CarriageReturns = value.Trim(); }
        }

        [XmlElement(DataType = "normalizedString")]
        public string Newlines
        {
            get { return _Newlines; }
            set { _Newlines = value.Trim(); }
        }

        [XmlElement(DataType = "normalizedString")]
        public string Spaces
        {
            get { return _Spaces; }
            set { _Spaces = value.Trim(); }
        }

        [XmlElement(DataType = "normalizedString")]
        public string Tabs
        {
            get { return _Tabs ; }
            set { _Tabs = value.Trim(); }
        }
    }

据我所知,当反序列化或序列化应用了
[xmldattribute(DataType=“normalizedString”)]
的字段时,System.Xml.Serialization没有做任何有意义的事情,因此,似乎没有任何设置可以使其正确地规范化空白

到目前为止,我能够获得可接受结果的唯一方法是创建一个实现
IXmlSerializable
NormalizedString
类,并使用该类代替基本
string
字段。最低限度的实现如下所示:

using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace XsdTypes
{
    public class NormalizedString : IXmlSerializable
    {
        public const char CR = '\u000d';
        public const char LF = '\u000a';
        public const char SPACE = '\u0020';
        public const char TAB = '\u0009';

        protected string value = null;

        public NormalizedString() { }

        public NormalizedString(NormalizedString value)
        {
            this.value = value.value;
        }

        public NormalizedString(String value)
        {
            this.value = NormalizeWhitespace(value);
        }

        public static string NormalizeWhitespace(string value)
        {
            if (!String.IsNullOrEmpty(value))
            {
                value = value.Replace(CR, SPACE).Replace(LF, SPACE).Replace(TAB, SPACE);
            }
            return value;
        }

        #region Class overrides

        public override string ToString()
        {
            return value;
        }

        #endregion

        #region IXmlSerializable

        XmlSchema IXmlSerializable.GetSchema()
        {
            return (null);
        }

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            //TODO: This could be null
            value = NormalizeWhitespace(reader.ReadString());
            reader.Read();
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            writer.WriteString(NormalizeWhitespace(value));
        }

        #endregion
    }
}
实现一般有用的类(
ICloneable
IComparable
IConvertible
IEquatable
、隐式运算符等)还有很多工作要做,但上述工作足以正确地反序列化和序列化以下类:

    [XmlRoot("Root")]
    public class Root
    {
        [XmlElement(IsNullable = true)]
        public NormalizedString CarriageReturns;
        [XmlElement(IsNullable = true)]
        public NormalizedString Linefeeds;
        [XmlElement(IsNullable = true)]
        public NormalizedString Spaces;
        [XmlElement(IsNullable = true)]
        public NormalizedString Tabs;
    }
这似乎比在需要
xs:normalizedString
元素的每个位置添加自定义getter和setter简单得多

请注意:如果您试图用
[xmlement(DataType=“NormalizedString”)]
装饰其中一个NormalizedString字段(或者
DataType=anything
),您将得到一个运行时异常:

以下NUnit3测试集执行XML反序列化和序列化:

// Install-Package NUnit
// Install-Package NUnit3TestAdapter
using NUnit.Framework;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace XsdTypes.NormalizedStringTests.IXmlSerializable
{
    [XmlRoot("Root")]
    public class Root
    {
        [XmlElement(IsNullable = true)]
        public NormalizedString CarriageReturns;
        [XmlElement(IsNullable = true)]
        public NormalizedString Linefeeds;
        [XmlElement(IsNullable = true)]
        public NormalizedString Spaces;
        [XmlElement(IsNullable = true)]
        public NormalizedString Tabs;
    }

    [TestFixture]
    public class NormalizedStringDeserializationTests
    {
        public Root root;

        [SetUp]
        public void SetUp()
        {
            var xml =
                "<Root>\r\n" +
                " <CarriageReturns> returns\u000d\u000dreturns </CarriageReturns>\r\n" +
                " <Linefeeds> linefeeds\u000a\u000alinefeeds </Linefeeds>\r\n" +
                " <Spaces> spaces\u0020\u0020spaces </Spaces>\r\n" +
                " <Tabs> tabs\u0009\u0009tabs </Tabs>\r\n" +
                "</Root>\r\n";
            Deserialize(xml);
        }

        private void Deserialize(string xml)
        {
            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
            {
                var serializer = new XmlSerializer(typeof(Root));
                root = (Root)serializer.Deserialize(stream);
            }
        }

        [Test]

        public void TestCarriageReturns()
        {
            string actual = root.CarriageReturns.ToString();
            Assert.That(actual, Is.EqualTo(" returns  returns "));
        }

        [Test]

        public void TestLinefeeds()
        {
            string actual = root.Linefeeds.ToString();
            Assert.That(actual, Is.EqualTo(" linefeeds  linefeeds "));
        }

        [Test]

        public void TestSpaces()
        {
            string actual = root.Spaces.ToString();
            Assert.That(actual, Is.EqualTo(" spaces  spaces "));
        }

        [Test]

        public void TestTabs()
        {
            string actual = root.Tabs.ToString();
            Assert.That(actual, Is.EqualTo(" tabs  tabs "));
        }

    }

    [TestFixture]
    public class NormalizedStringSerializationTests
    {
        string xml;

        [SetUp]
        public void SetUp()
        {
            var root = new Root()
            {
                CarriageReturns = new NormalizedString(" returns\u000d\u000dreturns "),
                Linefeeds = new NormalizedString(" linefeeds\u000d\u000dlinefeeds "),
                Spaces = new NormalizedString(" spaces\u000d\u000dspaces "),
                Tabs = new NormalizedString(" tabs\u000d\u000dtabs ")
            };
            Serialize(root);
        }

        private void Serialize(Root root)
        {
            using (var stream = new MemoryStream())
            {
                var serializer = new XmlSerializer(typeof(Root));
                serializer.Serialize(stream, root);
                xml = Encoding.UTF8.GetString(stream.ToArray());
            }
        }

        [Test]
        public void TestCarriageReturns()
        {
            Assert.That(xml, Does.Contain("<CarriageReturns> returns  returns </CarriageReturns>"));
        }

        [Test]
        public void TestLinefeeds()
        {
            Assert.That(xml, Does.Contain("<Linefeeds> linefeeds  linefeeds </Linefeeds>"));
        }

        [Test]
        public void TestNullables()
        {
            Serialize(new Root());
            Assert.That(xml, Does.Contain("<CarriageReturns xsi:nil=\"true\" />"));
            Assert.That(xml, Does.Contain("<Linefeeds xsi:nil=\"true\" />"));
            Assert.That(xml, Does.Contain("<Spaces xsi:nil=\"true\" />"));
            Assert.That(xml, Does.Contain("<Tabs xsi:nil=\"true\" />"));
        }

        [Test]
        public void TestSpaces()
        {
            Assert.That(xml, Does.Contain("<Spaces> spaces  spaces </Spaces>"));
        }

        [Test]

        public void TestTabs()
        {
            Assert.That(xml, Does.Contain("<Tabs> tabs  tabs </Tabs>"));
        }
    }
}
//安装包NUnit
//安装软件包NUnit3TestAdapter
使用NUnit.Framework;
使用System.IO;
使用系统文本;
使用System.Xml.Serialization;
命名空间XsdTypes.NormalizedStringTests.IXmlSerializable
{
[XmlRoot(“根”)]
公共类根
{
[XmlElement(IsNullable=true)]
公共规范化字符串返回;
[XmlElement(IsNullable=true)]
公共规范化字符串换行符;
[XmlElement(IsNullable=true)]
公共规范化字符串空间;
[XmlElement(IsNullable=true)]
公共规范化字符串选项卡;
}
[测试夹具]
公共类normalizedStringDeserialization测试
{
公共根;
[设置]
公共作废设置()
{
var-xml=
“\r\n”+
“返回\u000d\u000dreturns\r\n”+
“linefeeds\u000a\u000alinefeeds\r\n”+
“空间\u0020\u0020空间\r\n”+
“制表符\u0009\u0009制表符\r\n”+
“\r\n”;
反序列化(xml);
}
私有void反序列化(字符串xml)
{
使用(var stream=newmemoryStream(Encoding.UTF8.GetBytes(xml)))
{
var serializer=新的XmlSerializer(typeof(Root));
root=(root)序列化程序。反序列化(流);
}
}
[测试]
公共无效测试返回()
{
string actual=root.carinereturns.ToString();
断言(实际,即.EqualTo(“返回”));
}
[测试]
公共void TestLinefeeds()
{
字符串实际值=root.Linefeeds.ToString();
断言(实际的,是.EqualTo(“linefeeds linefeeds”);
}
[测试]
公共void TestSpaces()
{
string actual=root.Spaces.ToString();
断言(实际的,是.EqualTo(“空格”));
}
[测试]
公共void TestTabs()
{
string actual=root.Tabs.ToString();
断言(实际的,是.EqualTo(“tabs”));
}
}
// Install-Package NUnit
// Install-Package NUnit3TestAdapter
using NUnit.Framework;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace XsdTypes.NormalizedStringTests.IXmlSerializable
{
    [XmlRoot("Root")]
    public class Root
    {
        [XmlElement(IsNullable = true)]
        public NormalizedString CarriageReturns;
        [XmlElement(IsNullable = true)]
        public NormalizedString Linefeeds;
        [XmlElement(IsNullable = true)]
        public NormalizedString Spaces;
        [XmlElement(IsNullable = true)]
        public NormalizedString Tabs;
    }

    [TestFixture]
    public class NormalizedStringDeserializationTests
    {
        public Root root;

        [SetUp]
        public void SetUp()
        {
            var xml =
                "<Root>\r\n" +
                " <CarriageReturns> returns\u000d\u000dreturns </CarriageReturns>\r\n" +
                " <Linefeeds> linefeeds\u000a\u000alinefeeds </Linefeeds>\r\n" +
                " <Spaces> spaces\u0020\u0020spaces </Spaces>\r\n" +
                " <Tabs> tabs\u0009\u0009tabs </Tabs>\r\n" +
                "</Root>\r\n";
            Deserialize(xml);
        }

        private void Deserialize(string xml)
        {
            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
            {
                var serializer = new XmlSerializer(typeof(Root));
                root = (Root)serializer.Deserialize(stream);
            }
        }

        [Test]

        public void TestCarriageReturns()
        {
            string actual = root.CarriageReturns.ToString();
            Assert.That(actual, Is.EqualTo(" returns  returns "));
        }

        [Test]

        public void TestLinefeeds()
        {
            string actual = root.Linefeeds.ToString();
            Assert.That(actual, Is.EqualTo(" linefeeds  linefeeds "));
        }

        [Test]

        public void TestSpaces()
        {
            string actual = root.Spaces.ToString();
            Assert.That(actual, Is.EqualTo(" spaces  spaces "));
        }

        [Test]

        public void TestTabs()
        {
            string actual = root.Tabs.ToString();
            Assert.That(actual, Is.EqualTo(" tabs  tabs "));
        }

    }

    [TestFixture]
    public class NormalizedStringSerializationTests
    {
        string xml;

        [SetUp]
        public void SetUp()
        {
            var root = new Root()
            {
                CarriageReturns = new NormalizedString(" returns\u000d\u000dreturns "),
                Linefeeds = new NormalizedString(" linefeeds\u000d\u000dlinefeeds "),
                Spaces = new NormalizedString(" spaces\u000d\u000dspaces "),
                Tabs = new NormalizedString(" tabs\u000d\u000dtabs ")
            };
            Serialize(root);
        }

        private void Serialize(Root root)
        {
            using (var stream = new MemoryStream())
            {
                var serializer = new XmlSerializer(typeof(Root));
                serializer.Serialize(stream, root);
                xml = Encoding.UTF8.GetString(stream.ToArray());
            }
        }

        [Test]
        public void TestCarriageReturns()
        {
            Assert.That(xml, Does.Contain("<CarriageReturns> returns  returns </CarriageReturns>"));
        }

        [Test]
        public void TestLinefeeds()
        {
            Assert.That(xml, Does.Contain("<Linefeeds> linefeeds  linefeeds </Linefeeds>"));
        }

        [Test]
        public void TestNullables()
        {
            Serialize(new Root());
            Assert.That(xml, Does.Contain("<CarriageReturns xsi:nil=\"true\" />"));
            Assert.That(xml, Does.Contain("<Linefeeds xsi:nil=\"true\" />"));
            Assert.That(xml, Does.Contain("<Spaces xsi:nil=\"true\" />"));
            Assert.That(xml, Does.Contain("<Tabs xsi:nil=\"true\" />"));
        }

        [Test]
        public void TestSpaces()
        {
            Assert.That(xml, Does.Contain("<Spaces> spaces  spaces </Spaces>"));
        }

        [Test]

        public void TestTabs()
        {
            Assert.That(xml, Does.Contain("<Tabs> tabs  tabs </Tabs>"));
        }
    }
}