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”)); } } }
请注意,XmlSerializer实际上用换行符(\u000a)替换了回车符(\u000d),因此它在反序列化XML时进行了一些基本的规范化 ==== 编辑以使问题完全清楚: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类,以便所有替换测试都能通过吗?尝试以下方法:
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>"));
}
}
}