К сожалению. Net написан не для упрощения этой задачи. Один из подходов - создать оболочку для XmlWriter
, которая позволяет вам записывать необработанные значения атрибутов.
public class XmlRawAttribWriter : XmlWriter, IDisposable {
XmlWriter baseWriter;
bool disposedValue;
HashSet<string> RawAttributeNames;
bool LastAttributeIsRaw = false;
public XmlRawAttribWriter(XmlWriter b) => baseWriter = b;
public XmlRawAttribWriter(TextWriter output, XmlWriterSettings settings, string[] rawAttributeNames) {
RawAttributeNames = rawAttributeNames.ToHashSet();
baseWriter = XmlWriter.Create(output, settings);
}
public static XmlRawAttribWriter Create(TextWriter output, XmlWriterSettings settings, params string[] rawAttributeNames) => new XmlRawAttribWriter(output, settings, rawAttributeNames);
public override WriteState WriteState => baseWriter.WriteState;
public override void Flush() => baseWriter.Flush();
public override string LookupPrefix(string ns) => baseWriter.LookupPrefix(ns);
public override void WriteBase64(byte[] buffer, int index, int count) => baseWriter.WriteBase64(buffer, index, count);
public override void WriteCData(string text) => baseWriter.WriteCData(text);
public override void WriteCharEntity(char ch) => baseWriter.WriteCharEntity(ch);
public override void WriteChars(char[] buffer, int index, int count) => baseWriter.WriteChars(buffer, index, count);
public override void WriteComment(string text) => baseWriter.WriteComment(text);
public override void WriteDocType(string name, string pubid, string sysid, string subset) => baseWriter.WriteDocType(name, pubid, sysid, subset);
public override void WriteEndAttribute() {
LastAttributeIsRaw = false;
baseWriter.WriteEndAttribute();
}
public override void WriteEndDocument() => baseWriter.WriteEndDocument();
public override void WriteEndElement() => baseWriter.WriteEndElement();
public override void WriteEntityRef(string name) => baseWriter.WriteEntityRef(name);
public override void WriteFullEndElement() => baseWriter.WriteFullEndElement();
public override void WriteProcessingInstruction(string name, string text) => baseWriter.WriteProcessingInstruction(name, text);
public override void WriteRaw(char[] buffer, int index, int count) => baseWriter.WriteRaw(buffer, index, count);
public override void WriteRaw(string data) => baseWriter.WriteRaw(data);
public override void WriteStartAttribute(string prefix, string localName, string ns) {
LastAttributeIsRaw = RawAttributeNames.Contains(localName);
baseWriter.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteStartDocument() => baseWriter.WriteStartDocument();
public override void WriteStartDocument(bool standalone) => baseWriter.WriteStartDocument(standalone);
public override void WriteStartElement(string prefix, string localName, string ns) => baseWriter.WriteStartElement(prefix, localName, ns);
public override void WriteString(string text) {
if (LastAttributeIsRaw)
baseWriter.WriteRaw(text);
else
baseWriter.WriteString(text);
}
public override void WriteSurrogateCharEntity(char lowChar, char highChar) => baseWriter.WriteSurrogateCharEntity(lowChar, highChar);
public override void WriteWhitespace(string ws) => baseWriter.WriteWhitespace(ws);
protected override void Dispose(bool disposing) {
if (!disposedValue) {
if (disposing) {
baseWriter.Dispose();
}
disposedValue = true;
}
}
}
Вы можете использовать XmlRawAttribWriter
вместо XmlWriter
- вот несколько примеров использования:
public static class LinqXmlExt {
public static string GetRawAttribXmlString(this XNode x, params string[] rawAttributeNames) {
using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) {
var ws = new XmlWriterSettings();
ws.OmitXmlDeclaration = true;
ws.Indent = true;
if (x is XText)
ws.ConformanceLevel = ConformanceLevel.Fragment;
var sw2 = new StringWriter(CultureInfo.InvariantCulture);
var ws2 = new XmlWriterSettings();
using (var w = XmlRawAttribWriter.Create(sw, ws, rawAttributeNames)) {
x.WriteTo(w);
}
return sw.ToString();
}
}
public static string ToRawAttribString(this XNode x, params string[] rawAttributeNames) => x.GetRawAttribXmlString(rawAttributeNames);
}
С его помощью вы можете получить строку XML для XDocument
, имеющего необработанное значение атрибута:
var xmlString = xml.ToRawAttribString("MyValue");
При необходимости вы можете изменить XmlRawAttribWriter
для отслеживания текущего элемента, сохраняя localName
в методе WriteStartElement
, чтобы влиять только на атрибуты определенных элементов, передавая что-то вроде «element: attribute» для сопоставления.
Если вы используете другие методы (например, XDocument.Save
), вы можете создать соответствующие методы расширения (например, SaveRaw
), которые принимают имена атрибутов, чтобы их значения выводились как необработанные.