ถ้าใช้คำสั่งแล้วมี error
C:\Users\Thada\Desktop\PolarUK\Xml>xsd Eval_Imperial.xsd /classes /language:CS /namespace:ncs2polaruk
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.8.3928.0]
Copyright (C) Microsoft Corporation. All rights reserved.
Error: ‘.’, hexadecimal value 0x00, is an invalid character. Line 2, position 1.
จาก error message ที่ได้รับ: Error: '.', hexadecimal value 0x00, is an invalid character. Line 2, position 1.
ปัญหานี้ชัดเจนมากครับ สาเหตุหลักมาจาก File Encoding ของไฟล์ Eval_Imperial.xsd ไม่ถูกต้อง
ตัว error hexadecimal value 0x00 หมายถึง อักขระ NULL (NULL character) ซึ่งเป็นอักขระที่ไม่สามารถแสดงผลได้และไม่ควรมีอยู่ในไฟล์ XML/XSD ครับ parser ของ xsd.exe ไปเจออักขระนี้เข้าที่ บรรทัดที่ 2 ตำแหน่งแรกสุด ก็เลยหยุดทำงานทันที
ปัญหานี้มักจะเกิดขึ้นเมื่อไฟล์ถูกบันทึกด้วย encoding ที่ไม่เข้ากัน เช่น UTF-16 หรือ UTF-32 แล้ว parser พยายามจะอ่านเป็น UTF-8 ทำให้เกิดการตีความ “Byte Order Mark” (BOM) ที่อยู่ต้นไฟล์ผิดพลาดกลายเป็นอักขระ NULL ครับ
หลักๆก็คือ ตอนสร้างไฟล์ XSD ด้วย xsd-gen มันใช้ Encoding = UTF-16 LE
ก็ไม่รู้ทำไมถึงต้องใช้ UTF-16
แต่ถ้าเราไม่ได้สังเกตุอะไร เวลาเปิดด้วย Text-Editor เราก็จะเห็นเป็นไฟล์ text ธรรมดา
แต่เวลาเราเขียนโปรแกรม มันจะอ่านมาทีละ byte หรือทีละแถว ทีนี้ถ้าเราไม่กำหนดว่า encoding คืออะไร เวลามันอ่านเข้ามามันก็อ่านมาไม่ครบ ถ้า UTF-8 มี 2 byte UTF-16 ก็จะเป็น 2 เท่า เวลาอ่านผิด codec มันก็อ่านมาไม่ครบตัวอักษร
UTF-16 LE คือ วิธีการเข้ารหัสตัวอักษร (Character Encoding) รูปแบบหนึ่ง ซึ่งสามารถแบ่งความหมายออกเป็น 2 ส่วนคือ:
- UTF-16: เป็นมาตรฐานการเข้ารหัสตัวอักษรในระบบ Unicode ที่ใช้พื้นที่อย่างน้อย 16 บิต (หรือ 2 ไบต์) ในการเก็บข้อมูลสำหรับตัวอักษร 1 ตัว ทำให้สามารถรองรับตัวอักษรได้หลากหลายภาษาทั่วโลก (มากกว่าแบบ ANSI หรือ TIS-620 ที่ใช้แค่ 1 ไบต์) เป็นรูปแบบที่ระบบปฏิบัติการ Windows ใช้เป็นหลักภายในระบบ
- LE (Little Endian): นี่คือส่วนที่สำคัญที่สุดและเป็นต้นตอของปัญหาที่คุณเจอครับ “Endian” หมายถึง “ลำดับของการจัดเก็บไบต์ (Byte Order)” สำหรับข้อมูลที่ใหญ่กว่า 1 ไบต์
หัวใจสำคัญ: Endianness (การเรียงลำดับไบต์) 💾
เมื่อคอมพิวเตอร์จะเก็บข้อมูลที่มีขนาด 2 ไบต์ (เช่น เลข 258 ซึ่งในเลขฐาน 16 คือ 0102) มันมีวิธีเก็บ 2 แบบ:
- Big Endian (BE): “ใหญ่ไปเล็ก” คือเก็บไบต์ที่มีค่าสำคัญที่สุด (Most Significant Byte – MSB) ก่อน ตามด้วยไบต์ที่มีค่าน้อยกว่า
- เลข
0x0102จะถูกเก็บในหน่วยความจำเป็น0102(ตรงไปตรงมาเหมือนที่คนอ่าน)
- เลข
- Little Endian (LE): “เล็กไปใหญ่” คือเก็บไบต์ที่มีค่าสำคัญน้อยที่สุด (Least Significant Byte – LSB) ก่อน แล้วค่อยตามด้วยไบต์ที่มีค่ามากกว่า
- เลข
0x0102จะถูกเก็บในหน่วยความจำเป็น0201(สลับกัน)
- เลข
สถาปัตยกรรมของ CPU ส่วนใหญ่ในปัจจุบัน (เช่น Intel, AMD) ใช้แบบ Little Endian ครับ
แล้วมันเกี่ยวกับ UTF-16 LE อย่างไร?
เมื่อเราจะเก็บตัวอักษรด้วย UTF-16 ซึ่งใช้ 2 ไบต์ ก็ต้องเลือกว่าจะเก็บแบบไหน
ตัวอย่าง: ตัวอักษร 'A' ใน Unicode คือ U+0041 ซึ่งมี 2 ไบต์คือ 00 และ 41
- ถ้าเก็บแบบ UTF-16 BE (Big Endian) จะเก็บเป็น:
00 41 - ถ้าเก็บแบบ UTF-16 LE (Little Endian) จะเก็บเป็น:
41 00
สาเหตุของ Error ที่คุณเจอ
ไฟล์ที่บันทึกเป็น UTF-16 มักจะมีอักขระพิเศษ 2 ไบต์นำหน้าไฟล์ที่เรียกว่า Byte Order Mark (BOM) เพื่อบอกให้โปรแกรมที่มาเปิดไฟล์รู้ว่าควรจะอ่านไบต์แบบไหน
- UTF-16 LE จะมี BOM เป็น
FF FE - UTF-16 BE จะมี BOM เป็น
FE FF

