C# UTF8 XML文档中ASCII字符串的字节数组编码
我有以下几点要求: …文档必须用UTF-8编码。。。Lastname字段仅允许(扩展)ASCIICity仅允许ISOLatin1 …消息必须作为IBytesMessage放在(IBM Websphere)消息队列中 为简单起见,XML文档如下所示:C# UTF8 XML文档中ASCII字符串的字节数组编码,c#,encoding,utf-8,ascii,C#,Encoding,Utf 8,Ascii,我有以下几点要求: …文档必须用UTF-8编码。。。Lastname字段仅允许(扩展)ASCIICity仅允许ISOLatin1 …消息必须作为IBytesMessage放在(IBM Websphere)消息队列中 为简单起见,XML文档如下所示: <?xml version="1.0" encoding="utf-8"?> <foo> <lastname>John ÐØë</lastname> <city>John ÐØë&l
<?xml version="1.0" encoding="utf-8"?>
<foo>
<lastname>John ÐØë</lastname>
<city>John ÐØë</city>
<other>UTF-8 string</other>
</foo>
因此,我实例化一个对象并设置lastname:
var x = new foo() { lastname = "John ÐØë", city = "John ÐØë" };
这就是我头疼的地方(或者如果你愿意的话…):
- Visual studio/源代码是Unicode格式的
- 因此:对象具有Unicodelastname
- XML序列化程序使用UTF-8对文档进行编码
- Lastname应仅包含(扩展)ASCII字符;字符是有效的ASCII字符,但当然是UTF-8编码形式
c3xx c3xx c3xx
(我手头没有实际转储)。很明显(或者我已经盯着它太久了),lastname/city字符串是以unicode格式放在序列化文档中的;字节数组表明了这一点
现在,我必须做什么,在哪里,以确保Lastname字符串进入XML文档,最后是字节数组作为ASCII字符串(以及实际的208、216、235字节序列),并且该城市将其作为ISOLatin1放入其中
我知道这些要求是倒退的,但我不能改变这些(第三方)。我总是在我们的内部项目中使用UTF-8,所以我必须支持unicode-utf8=>ASCII/ISOLatin1转换(当然,只支持那些集合中的字符)
我的头疼…所以
System.Text.Encoding.ASCII.GetBytes(string)
可能会执行您想要的操作。。将字符串转换为ascii编码的字节数组。在UTF-8编码的字符串/字节数组中不能有208、216、235字节序列
我希望您可以将XML另存为ISO 8859-1,无论是否在XML
处理指令中提及它(甚至可能在XML头中指定无效的UTF-8编码)
否则,如果您的需求如您所述,只需为给定的输入请求准确的预期字节数组,并创建您自己的自定义序列化(或者自定义编码,也不确定是否可行)
文档必须用UTF-8编码。Lastname
字段仅允许使用ASCII<代码>城市仅允许隔离1。消息必须作为IBytesMessage
放在(IBM Websphere)MessageQueue
上
如果这是准确的规格,那么我想你可能会误解它。您的任务不是编码,而是验证/回退。整个文档(包括Lastname
和City
字段)必须编码为UTF-8。很简单,如果XML文档将其编码声明为UTF-8,然后包含在该编码下无效的字节值,那么它将无效
方便的是,ASCII与Unicode的前128个代码点重叠;Latin1与前256重叠
要检查Lastname
是否可以表示为ASCII,则可以检查其所有字符的代码点是否在0–127范围内
bool isLastnameAscii = foo.Lastname.All(c => (int)c < 128);
类似地,对于城市:
bool isCityLatin1 = foo.City.All(c => (int)c < 256);
Encoding latin1 = Encoding.GetEncoding("iso-8859-1");
foo.City = latin1.GetString(latin1.GetBytes(foo.City));
SecurityElement.Escape
将字符串中的无效XML字符替换为其有效的等效XML字符(例如,不管XML文档是如何编码以进行传输的。正确的方法是对某些非ASCII字符进行编码,以使它们在传输过程中不受损害。使用表示需要保留的字符。例如
ÐØë
使用as表示
接收[conformant]XML处理器将/应该/必须将这些数字字符引用转换回它们所表示的字符。下面是一些代码:
public static string ConvertToXmlCharacterReference( this string xml )
{
StringBuilder sb = new StringBuilder( s.Length ) ;
const char SP = '\u0020' ; // anything lower than SP is a control character
const char DEL = '\u007F' ; // anything above DEL isn't ASCII, per se.
foreach( char ch in xml )
{
bool isPrintableAscii = ch >= SP && ch <= DEL ;
if ( isPrintableAscii ) { sb.Append(ch) ; }
else { sb.AppendFormat( "&#x{0:X4}" , (int) ch ) ; }
}
string instance = sb.ToString() ;
return instance ;
}
public静态字符串ConvertToXmlCharacterReference(此字符串为xml)
{
StringBuilder sb=新StringBuilder(s.长度);
const char SP='\u0020';//任何低于SP的字符都是控制字符
const char DEL='\u007F';//DEL之上的任何内容本身都不是ASCII。
foreach(xml中的char-ch)
{
bool isPrintableAscii=ch>=SP&&chNicholas Carey接受的答案是可以的,但它有错误,代码不起作用。我没有足够的声誉发表评论,因此我将在此处编写工作代码:
public static string ConvertToXmlCharacterReference(string xml)
{
StringBuilder sb = new StringBuilder();
const char SP = '\u0020'; // anything lower than SP is a control character
const char DEL = '\u007F'; // anything above DEL isn't ASCII, per se.
int i = 0;
foreach (char ch in xml)
{
bool isPrintableAscii = ch >= SP && ch <= DEL;
if (isPrintableAscii)
{
sb.Append(ch);
}
else
{
sb.AppendFormat("&#x{0:X4};", (int) ch);
}
}
string instance = sb.ToString();
return instance;
}
public静态字符串ConvertToXmlCharacterReference(字符串xml)
{
StringBuilder sb=新的StringBuilder();
const char SP='\u0020';//任何低于SP的字符都是控制字符
const char DEL='\u007F';//DEL之上的任何内容本身都不是ASCII。
int i=0;
foreach(xml中的char-ch)
{
bool isPrintableAscii=ch>=SP&&ch我将此理解为两个独立的要求:
1) XML必须是UTF-8编码的
2) 城市名称仅限于ISOLatin1
这意味着当您将UTF-8解码为未编码时,城市字符仅来自ISOLatin1集合。换句话说,XML可以进行ISOLatin1编码(所有文本都来自ISOLatin1代码表),但它是UTF-8。ISOLatin1是Unicode表的一小部分,UTF-8是Unicode的8位编码。“ØØë”部分是(或应该是)ASCII值分别为208、216、235。”这是毫无意义的。没有ASCII值大于127的,这称为扩展A
ÐØë
ÐØë
public static string ConvertToXmlCharacterReference( this string xml )
{
StringBuilder sb = new StringBuilder( s.Length ) ;
const char SP = '\u0020' ; // anything lower than SP is a control character
const char DEL = '\u007F' ; // anything above DEL isn't ASCII, per se.
foreach( char ch in xml )
{
bool isPrintableAscii = ch >= SP && ch <= DEL ;
if ( isPrintableAscii ) { sb.Append(ch) ; }
else { sb.AppendFormat( "&#x{0:X4}" , (int) ch ) ; }
}
string instance = sb.ToString() ;
return instance ;
}
public static string ConvertToXmlCharacterReference(string xml)
{
StringBuilder sb = new StringBuilder();
const char SP = '\u0020'; // anything lower than SP is a control character
const char DEL = '\u007F'; // anything above DEL isn't ASCII, per se.
int i = 0;
foreach (char ch in xml)
{
bool isPrintableAscii = ch >= SP && ch <= DEL;
if (isPrintableAscii)
{
sb.Append(ch);
}
else
{
sb.AppendFormat("&#x{0:X4};", (int) ch);
}
}
string instance = sb.ToString();
return instance;
}