Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# UTF8 XML文档中ASCII字符串的字节数组编码_C#_Encoding_Utf 8_Ascii - Fatal编程技术网

C# UTF8 XML文档中ASCII字符串的字节数组编码

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

我有以下几点要求:

…文档必须用UTF-8编码。。。Lastname字段仅允许(扩展)ASCIICity仅允许ISOLatin1 …消息必须作为IBytesMessage放在(IBM Websphere)消息队列中

为简单起见,XML文档如下所示:

<?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编码形式
我通常不会遇到编码方面的任何问题;我很熟悉,但这件事让我很困惑

我知道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
ÐØë
&#x00D0;&#x00D8;&#x00EB;
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;
    }