Документ должен быть закодирован в UTF-8.Поле Lastname
допускает только ASCII.City
разрешает только ISOLatin1.Сообщение (IBM Websphere) MessageQueue
должно быть записано как IBytesMessage
.
Если это точная спецификация, то я думаю, что вы, возможно, неправильно ее поняли.Ваша задача - не кодирование, а проверка / откат.Весь документ , включая поля Lastname
и City
, должен быть закодирован как UTF-8.Проще говоря, документ XML был бы недействительным, если бы он объявил свою кодировку как UTF-8, а затем содержал байтовые значения, которые недопустимы в этой кодировке.
Удобно, ASCII перекрывается с первыми 128 кодовыми точками Unicode;Latin1 перекрывается с первым 256.
Чтобы проверить, может ли Lastname
быть представлен как ASCII, вы можете проверить, что все его символы имеют кодовые точки в диапазоне 0–127.
bool isLastnameAscii = foo.Lastname.All(c => (int)c < 128);
Чтобы соответствовать вашей спецификации, вам придется заставить недопустимые символы возвращаться к символу замены (обычно ?
), кодируя строку как ASCII, а затем декодируя ее обратно:
foo.Lastname = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(foo.Lastname));
Аналогичнодля City
:
bool isCityLatin1 = foo.City.All(c => (int)c < 256);
Encoding latin1 = Encoding.GetEncoding("iso-8859-1");
foo.City = latin1.GetString(latin1.GetBytes(foo.City));
Впоследствии вы должны просто сохранить все как UTF-8.
Я предполагаю, что ваше стороннее программное обеспечение может правильно декодироватьXML-документ с использованием UTF-8;однако он должен затем извлечь поля Lastname
и City
и использовать их где-нибудь, где разрешены только ASCII и Latin1.Он налагает на вас ограничения, чтобы гарантировать, что он не будет вынужден нести потерю данных (из-за наличия запрещенных символов).
Редактировать : это обходной путь, который выпредлагаешь.Я использую Latin1 вместо «Extended ASCII», потому что последний термин неоднозначный.
var x = new foo() { lastname = "John ÐØë", city = "John ÐØë", other = "—" };
using (var stream = new MemoryStream())
using (var utf8writer = new StreamWriter(stream, Encoding.UTF8))
using (var latin1writer = new StreamWriter(stream, Encoding.GetEncoding("iso-8859-1")))
{
utf8writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
utf8writer.WriteLine("<foo>");
utf8writer.Flush();
latin1writer.WriteLine(" <lastname>" + SecurityElement.Escape(x.lastname) + "</lastname>");
latin1writer.WriteLine(" <city>" + SecurityElement.Escape(x.city) + "</city>");
latin1writer.Flush();
utf8writer.WriteLine(" <other>" + SecurityElement.Escape(x.other) + "</other>");
utf8writer.WriteLine("/<foo>");
utf8writer.Flush();
byte[] bytes = stream.ToArray();
}
SecurityElement.Escape
заменяет недопустимые символы XML в строке их действительным эквивалентом XML (например, <
для<
и &
до &
).