XDocument.ToString () usuwa znacznik kodowania XML


103

Czy istnieje sposób uzyskania kodowania XML w funkcji toString ()?

Przykład:

xml.Save("myfile.xml");

prowadzi do

<?xml version="1.0" encoding="utf-8"?>
<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>

Ale

tb_output.Text = xml.toString();

prowadzi do takiego wyniku

<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>
    ...

Odpowiedzi:


98

Albo jawnie napisz deklarację, albo użyj a StringWriteri wywołaj Save():

using System;
using System.IO;
using System.Text;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        string xml = @"<?xml version='1.0' encoding='utf-8'?>
<Cooperations>
  <Cooperation />
</Cooperations>";

        XDocument doc = XDocument.Parse(xml);
        StringBuilder builder = new StringBuilder();
        using (TextWriter writer = new StringWriter(builder))
        {
            doc.Save(writer);
        }
        Console.WriteLine(builder);
    }
}

Możesz łatwo dodać to jako metodę rozszerzenia:

public static string ToStringWithDeclaration(this XDocument doc)
{
    if (doc == null)
    {
        throw new ArgumentNullException("doc");
    }
    StringBuilder builder = new StringBuilder();
    using (TextWriter writer = new StringWriter(builder))
    {
        doc.Save(writer);
    }
    return builder.ToString();
}

Ma to tę zaletę, że nie wybuchnie, jeśli nie ma deklaracji :)

Następnie możesz użyć:

string x = doc.ToStringWithDeclaration();

Zauważ, że użyje to utf-16 jako kodowania, ponieważ jest to niejawne kodowanie w StringWriter. Możesz jednak wpłynąć na to samodzielnie, tworząc podklasę StringWriter, np. Aby zawsze używać UTF-8 .


14
Ma to mały problem polegający na tym, że kodowanie w deklaracji XDocument jest ignorowane i zastępowane przez kodowanie StringWriter podczas zapisywania, co może być tym, czego chcesz, ale nie musi
— Sam Holder

2
Następnie łączysz metodę rozszerzenia z: Utf8StringWriter ze stackoverflow.com/a/1564727/75963 ;)
— Nick Josevski

12
Zauważyłem, że łatwiej jest użyć powyższej metody rozszerzającej, ale zwróć następujące ... return doc.Declaration + doc.ToString (); Jeśli deklaracja ma wartość null, skutkuje po prostu pustym ciągiem.
— Steve G.

Dziwne, ale nie mogę go teraz uruchomić ( skrzypce .net ) - zawsze używa kodowania "utf-16". Zajrzałem do wnętrza XDocument.Save(TextWriter)implementacji i po prostu ignoruje kodowanie deklaracji, w przeciwieństwie do implementacji XDocument.Save(String)lub XDocument.Save(Stream). Zastanawiam się, dlaczego ...
— Ilya Luzyanin

@IlyaLuzyanin: Tak, użyje "utf-16" jako kodowania, kiedy przekażesz a StringWriter, chyba że użyjesz takiego, który nadpisuje Encodingwłaściwość. Mam inną odpowiedź na ten temat. Myślałem, że mówisz, że całkowicie porzuciłeś "kodowanie" ...
— Jon Skeet

46

Właściwość Declaration będzie zawierać deklarację XML. Aby uzyskać treść plus deklarację, możesz wykonać następujące czynności:

tb_output.Text = xml.Declaration.ToString() + xml.ToString()

7
wygląda na to, że jeśli nie używasz nowej XDeclaration ("1.0", "utf-8", "tak") w swoim xdocument, spowoduje to błąd, ponieważ xml.Declaration ma wartość null. Ale xml.save wydaje się automatycznie wykrywać właściwe kodowanie.
— Henrik P. Hessel

lubtb_output.Text = @"<?xml version=""1.0"" encoding=""utf-8"" ?>" + xml;
— Bill Hoag

4
lub... = $"{xdoc.Declaration}{Environment.NewLine}{xdoc}";
— WernerCD,

9

Użyj tego:

output.Text = String.Concat(xml.Declaration.ToString() , xml.ToString())

2
Bez tworzenia nowej deklaracji XDeclaration ("1.0", "utf-8", "tak") i dodawania do XDocument lub innego obiektu, xml.Declaration.ToString () wyrzuci wyjątek zerowy.
— Ziggler

1
jest bezpieczniejsze jak poniżej, ponieważ Concat nie dba o ciągi zerowe: output.Text = String.Concat (xml.Declaration, xml)
— dmihailescu

3

Podobało mi się to

        string distributorInfo = string.Empty;

        XDocument distributors = new XDocument();

     //below is important else distributors.Declaration.ToString() throws null exception
        distributors.Declaration = new XDeclaration("1.0", "utf-8", "yes"); 

        XElement rootElement = new XElement("Distributors");
        XElement distributor = null;
        XAttribute id = null;

        distributor = new XElement("Distributor");
        id = new XAttribute("Id", "12345678");
        distributor.Add(id);
        rootElement.Add(distributor);

        distributor = new XElement("Distributor");
        id = new XAttribute("Id", "22222222");

        distributor.Add(id);

        rootElement.Add(distributor);         

        distributors.Add(rootElement);

        distributorInfo = String.Concat(distributors.Declaration.ToString(), distributors.ToString());

Zobacz poniżej, co otrzymuję w DistributorInfo

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Distributors>
  <Distributor Id="12345678" />
  <Distributor Id="22222222" />
  <Distributor Id="11111111" />
</Distributors>

1
dobry przykład. kilka uwag: 1) użyj nowej XDeclaration ("1.0", "utf-8") zamiast nowej XDeclaration ("1.0", "utf-8", "tak"), 2) wstaw nową linię w ostatniej linii: dystrybutorzy. Declaration.ToString () + Environment.NewLine + distributors.ToString ()
— Alexey Obukhov

2

Podobnie jak inne odpowiedzi +1, ale trochę więcej szczegółów na temat deklaracji i nieco dokładniejsza konkatenacja.

<xml />deklaracja powinna znajdować się w osobnym wierszu w sformatowanym pliku XML, więc upewniam się, że dodano nową linię. UWAGA: użycie Environment.Newlinetak spowoduje utworzenie nowej linii specyficznej dla platformy

// Parse xml declaration menthod
XDocument document1 =
  XDocument.Parse(@"<?xml version=""1.0"" encoding=""iso-8859-1""?><rss version=""2.0""></rss>");
string result1 =
  document1.Declaration.ToString() +
  Environment.NewLine +
  document1.ToString() ;

// Declare xml declaration method
XDocument document2 = 
  XDocument.Parse(@"<rss version=""2.0""></rss>");
document2.Declaration =
  new XDeclaration("1.0", "iso-8859-1", null);
string result2 =
  document2.Declaration.ToString() +
  Environment.NewLine +
  document2.ToString() ;

Oba wyniki dają:

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"></rss>

1

Kilka z tych odpowiedzi rozwiązuje prośbę nadawcy, ale wydaje się, że jest to zbyt skomplikowane. Oto prosta metoda rozszerzenia, która pozwala uniknąć konieczności stosowania oddzielnego modułu zapisującego, obsługuje brakującą deklarację i obsługuje standardowy parametr ToString SaveOptions.

public static string ToXmlString(this XDocument xdoc, SaveOptions options = SaveOptions.None)
{
    var newLine =  (options & SaveOptions.DisableFormatting) == SaveOptions.DisableFormatting ? "" : Environment.NewLine;
    return xdoc.Declaration == null ? xdoc.ToString(options) : xdoc.Declaration + newLine + xdoc.ToString(options);
}

Aby użyć rozszerzenia, po prostu wymień xml.ToString() goxml.ToXmlString()


0

Możesz również użyć XmlWriter i wywołać metodę

Writer.WriteDocType() 

metoda.


0
string uploadCode = "UploadCode";
string LabName = "LabName";
XElement root = new XElement("TestLabs");
foreach (var item in returnList)
{  
       root.Add(new XElement("TestLab",
                new XElement(uploadCode, item.UploadCode),
                new XElement(LabName, item.LabName)
                            )
               );
}

XDocument returnXML = new XDocument(new XDeclaration("1.0", "UTF-8","yes"),
             root);

string returnVal;
using (var sw = new MemoryStream())
{
       using (var strw = new StreamWriter(sw, System.Text.UTF8Encoding.UTF8))
       {
              returnXML.Save(strw);
              returnVal = System.Text.UTF8Encoding.UTF8.GetString(sw.ToArray());
       }
}

// ReturnVal has the string with XML data with XML declaration tag
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.