XmlWriter, aby zapisać do ciągu zamiast do pliku


118

Mam usługę WCF, która musi zwrócić ciąg XML. Ale wygląda na to, że piszący chce tylko utworzyć plik, a nie ciąg. Próbowałem:

string nextXMLstring = "";
using (XmlWriter writer = XmlWriter.Create(nextXMLstring))

To generuje błąd informujący, że nextXMLstring nie ma ścieżki do pliku. Chce czegoś takiego:

using (XmlWriter writer = XmlWriter.Create("nextXMLstring.xml"))

Jak mogę zbudować mój XML, a następnie zwrócić go jako ciąg?

Dzięki!!

Odpowiedzi:


217

Musisz utworzyć StringWriter i przekazać go do XmlWriter.

Przeciążenie ciągu XmlWriter.Create dotyczy nazwy pliku.

Na przykład

using (var sw = new StringWriter()) {
  using (var xw = XmlWriter.Create(sw)) {
    // Build Xml with xw.


  }
  return sw.ToString();
}

2
@Will: Cofnięto twoją zmianę. XmlTextWriter.Close () opróżni strumień do strumienia, więc postaraj się, aby stało się to przed wyodrębnieniem ciągu. (Mała różnica w tym przypadku, ale wolę robić to konsekwentnie, ponieważ semantyka flush klas * Writer i Stream nie zawsze jest jasno udokumentowana).
— Richard

1
Tylko komentarz dla osób używających tego. Jeśli zdarzy ci się pominąć using () i zamiast tego normalnie zadeklarować XmlWriter, upewnij się, że wywołałeś xw.Flush przed wywołaniem sw.ToString (), w przeciwnym razie możesz nie uzyskać całej zawartości! (Oczywiście lepiej jest użyć nawiasów klamrowych ...)
— Ravendarksky

Należy pamiętać, że poniższy kod ostrzega CA2202 podczas analizy kodu, metoda beacuse Dispose () zostanie wywołana dwukrotnie na obiekcie StringWriter
— Łukasz Kosiak

113

Jak powiedział Richard, StringWriterjest droga naprzód. Jest jednak jeden problem: domyślnie StringWriterbędzie się reklamować jako będący w UTF-16. Zwykle XML jest w UTF-8. Możesz to naprawić, tworząc podklasę StringWriter;

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding
    {
         get { return Encoding.UTF8; }
    }
}

Wpłynie to na oświadczenie sporządzone przez XmlWriter. Oczywiście, jeśli następnie napiszesz ciąg w innym miejscu w formie binarnej, upewnij się, że używasz kodowania, które pasuje do dowolnego kodowania, które naprawisz dla StringWriter. (Powyższy kod zawsze zakłada UTF-8; trywialne jest stworzenie bardziej ogólnej wersji, która akceptuje kodowanie w konstruktorze.)

Wtedy użyłbyś:

using (TextWriter writer = new Utf8StringWriter())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(writer))
    {
        ...
    }
    return writer.ToString();
}

Jon, jesteś pewien, że writerto nie jest usuwane więcej niż raz?
— rasx

2
@rasx: Może - ale to nie ma znaczenia.
— Jon Skeet

30

Wiem, że to jest stare i odpowiedziałem, ale oto inny sposób, aby to zrobić. Szczególnie jeśli nie chcesz, aby BOM UTF8 znajdował się na początku ciągu i chcesz, aby tekst był wcięty:

using (var ms = new MemoryStream())
using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
                   { Formatting = Formatting.Indented })
{
     // ...
     return Encoding.UTF8.GetString(ms.ToArray());
}

3
Encoding.UTF8.GetString(ms.ToArray())to uproszczenie po powrocie.
— SliverNinja - MSFT

1
ms.ToArray()nie zwraca żadnych pozycji, gdy próbowałem tego. Musiał dodać x.Close()lub przenieść instrukcję return tuż poza wewnętrzną instrukcję using.
— Rich C

Czy utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); praca?
— brianary

1
@Rich C - Podejrzewam, że to dlatego, że Twój strumień nie został opróżniony. XmlTextWriter zostałby usunięty poza jego instrukcją using, która spowodowałaby opróżnienie.
— yourbuddypal

13

Zastosowanie StringBuilder:

var sb = new StringBuilder();
    using (XmlWriter xmlWriter = XmlWriter.Create(sb))
    {
        ...
    }
return sb.ToString();

1

Chłopaki nie zapominają o wywołaniu xmlWriter.Close () i xmlWriter.Dispose (), bo inaczej twój string nie zakończy tworzenia. Będzie to po prostu pusty ciąg


Nie martw się, instrukcja using zajmie się usunięciem obiektu.

To jest pytanie z 2009 roku. Dlatego udzielenie odpowiedzi teraz byłoby przydatne dla przyszłych użytkowników, którzy mogą mieć podobne problemy. W związku z tym odpowiedzi na stare pytania, takie jak to, należy udzielić tylko wtedy, gdy mogą one jasno zidentyfikować problem i wyjaśnić / zapewnić rozwiązanie. Zazwyczaj próba angażowania OP w rozmowę jest bezowocna, ponieważ prawdopodobnie przeszli dalej.
— MikeC

Przeglądałem wszystkie te przykłady i zastanawiałem się, dlaczego otrzymuję pusty ciąg. xmlWriter.Close()było rozwiązaniem.
— Rafał Ryszkowski

-1

Cóż, myślę, że najprostszym i najszybszym rozwiązaniem byłoby po prostu:

StringBuilder sb = new StringBuilder();

using (var writer = XmlWriter.Create(sb, settings))
{
    ... // Whatever code you have/need :)

    sb = sb.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); //Or whatever uft you want/use.
    //Before you finally save it:
    File.WriteAllText("path\\dataName.xml", sb.ToString());
}
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.