Відповіді:
А-а ... ніколи не пам'ятаю. Завжди пошук після поставленого питання дає відповідь. Мій об’єкт, який серіалізується, є obj
і вже визначений. Додавання XMLSerializerNamespace з єдиним порожнім простором імен до колекції робить фокус.
У VB так:
Dim xs As New XmlSerializer(GetType(cEmploymentDetail))
Dim ns As New XmlSerializerNamespaces()
ns.Add("", "")
Dim settings As New XmlWriterSettings()
settings.OmitXmlDeclaration = True
Using ms As New MemoryStream(), _
sw As XmlWriter = XmlWriter.Create(ms, settings), _
sr As New StreamReader(ms)
xs.Serialize(sw, obj, ns)
ms.Position = 0
Console.WriteLine(sr.ReadToEnd())
End Using
в C #, як це:
//Create our own namespaces for the output
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
//Add an empty namespace and empty value
ns.Add("", "");
//Create the serializer
XmlSerializer slz = new XmlSerializer(someType);
//Serialize the object with our own namespaces (notice the overload)
slz.Serialize(myXmlTextWriter, someObject, ns);
q1
лайно?
Якщо ви хочете позбутися зайвого xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
та xmlns:xsd="http://www.w3.org/2001/XMLSchema"
, але все ж зберігати власну область імен xmlns="http://schemas.YourCompany.com/YourSchema/"
, використовуєте той же код, що і вище, за винятком цієї простої зміни:
// Add lib namespace with empty prefix
ns.Add("", "http://schemas.YourCompany.com/YourSchema/");
Якщо ви хочете видалити простір імен, ви також можете видалити версію, щоб заощадити пошук. Я додав цю функціональність, тому наведений нижче код буде виконувати і те, і інше.
Я також загорнув його в загальний метод, оскільки я створюю дуже великі файли XML, які занадто великі, щоб серіалізувати в пам'яті, тому я зламав вихідний файл вниз і серіалізував його на менші "шматки":
public static string XmlSerialize<T>(T entity) where T : class
{
// removes version
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
using (StringWriter sw = new StringWriter())
using (XmlWriter writer = XmlWriter.Create(sw, settings))
{
// removes namespace
var xmlns = new XmlSerializerNamespaces();
xmlns.Add(string.Empty, string.Empty);
xsSubmit.Serialize(writer, entity, xmlns);
return sw.ToString(); // Your XML
}
}
StringWriter
за замовчуванням кодування UTF-16, яке може призвести до проблем десеріалізації нижче за течією. using (var reader = XmlReader.Create(stream)){ reader.Read(); }
Це є винятком, оскільки в декларації зазначено, що це UTF-16, тоді як вміст насправді був написаний як UTF-8. System.Xml.XmlException: 'There is no Unicode byte order mark. Cannot switch to Unicode.'
XmlReader
, ви можете використовувати var streamReader = new StreamReader(stream, System.Text.Encoding.UTF8, true);
Істинний буде використовувати BOM, якщо він знайдеться, інакше вказаний вами за замовчуванням.
Я пропоную цей клас помічників:
public static class Xml
{
#region Fields
private static readonly XmlWriterSettings WriterSettings = new XmlWriterSettings {OmitXmlDeclaration = true, Indent = true};
private static readonly XmlSerializerNamespaces Namespaces = new XmlSerializerNamespaces(new[] {new XmlQualifiedName("", "")});
#endregion
#region Methods
public static string Serialize(object obj)
{
if (obj == null)
{
return null;
}
return DoSerialize(obj);
}
private static string DoSerialize(object obj)
{
using (var ms = new MemoryStream())
using (var writer = XmlWriter.Create(ms, WriterSettings))
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(writer, obj, Namespaces);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public static T Deserialize<T>(string data)
where T : class
{
if (string.IsNullOrEmpty(data))
{
return null;
}
return DoDeserialize<T>(data);
}
private static T DoDeserialize<T>(string data) where T : class
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(data)))
{
var serializer = new XmlSerializer(typeof (T));
return (T) serializer.Deserialize(ms);
}
}
#endregion
}
:)
new XmlSerializerNamespaces(new[] {XmlQualifiedName.Empty})
замість new XmlSerializerNamespaces(new[] {new XmlQualifiedName("", "")})
- це, на мою думку, навмисне зрозуміліший спосіб кодування.
Якщо ви не можете позбутися зайвих атрибутів xmlns для кожного елемента, під час серіалізації до xml з генерованих класів (наприклад, коли xsd.exe використовувався), то у вас є щось на кшталт:
<manyElementWith xmlns="urn:names:specification:schema:xsd:one" />
то я б поділився з вами тим, що працювало на мене (суміш попередніх відповідей і що я тут знайшов )
явно встановіть усі ваші різні xmlns наступним чином:
Dim xmlns = New XmlSerializerNamespaces()
xmlns.Add("one", "urn:names:specification:schema:xsd:one")
xmlns.Add("two", "urn:names:specification:schema:xsd:two")
xmlns.Add("three", "urn:names:specification:schema:xsd:three")
потім передайте його до серіалізації
serializer.Serialize(writer, object, xmlns);
у вас будуть три простори імен, оголошені в кореневому елементі, і більше не потрібно створювати інші елементи, які будуть відповідно встановлені
<root xmlns:one="urn:names:specification:schema:xsd:one" ... />
<one:Element />
<two:ElementFromAnotherNameSpace /> ...
XmlWriterSettings settings = new XmlWriterSettings
{
OmitXmlDeclaration = true
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
StringBuilder sb = new StringBuilder();
XmlSerializer xs = new XmlSerializer(typeof(BankingDetails));
using (XmlWriter xw = XmlWriter.Create(sb, settings))
{
xs.Serialize(xw, model, ns);
xw.Flush();
return sb.ToString();
}