Сохраните XML как XmlTextWriter, но с DOM

Когда я создаю XML в C# с использованием XmlDocument и хочу сохранить в XML файл, включая информацию о кодировке, я использую XmlTextWriter, как показано ниже:

    using (StringWriter swr = new StringWriter())
    {
        using (XmlTextWriter xtw = new XmlTextWriter(swr))
        {
            xmlDoc.WriteTo(xtw);
            return swr.ToString();
        }
    }

С помощью приведенного выше кода возвращаемая строка имеет следующий синтаксис:

<?xml version="1.0" encoding="utf-8"?>
<regs>
  <reg1>
....
  </reg1>
</regs>

Я хотел бы иметь то же поведение, используя методы IXMLDOMDocument. В этом кенарио я знаю, как извлечь строку XML только через xmlDoc.xml метод. Однако, используя этот метод, строка совершенно иная, как и кодировка:

<?xml version="1.0"?>
<regs>
  <reg1>
....
  </reg1>
</regs>

Есть ли способ вывести IXMLDOMDocument так же, как я получаю с XmlTextWriter, и с теми же результатами кодирования?
Tks

редактировать

Код, который я использую для генерации XML через DOM, находится на Delphi:

function TXMLClass.GenerateXML: Variant;
var
  iCont: Integer;
  sName, sValor: String;
  vXML: Variant;
  oNodeDados, oNodeCliente, oNodeTransacao: Variant;
  oHeader: Variant;
begin
  vXML := CreateOLEObject('Msxml2.DOMDocument.6.0');
  try
    oHeader := vXML.createProcessingInstruction('xml', 'version=''1.0'' encoding=''utf-8''');
    vXML.AppendChild(oHeader);
    oNodeDados := vXML.CreateElement('regs');
    vXML.AppendChild(oNodeDados);
    oNodeCliente := vXML.CreateElement('reg1');
    oNodeDados.AppendChild(oNodeCliente);
    Result := vXML;
  except
    on e: Exception do
    begin
      vXML := Unassigned;
      Result := vXML;
      raise;
    end;
  end;
end;

Моя главная проблема - результирующее кодирование строки, потому что я передаю полученную WideString в C# WebService, и когда я читаю ее в XmlDocument, все символы с любым акцентом ошибочны. Когда я генерирую XML в C#, экспортирую его через XmlTextWriter и отправляю обратно в Delphi, и я загружаю его через DOM, символы правильные.

редактировать

Когда я использую vXML.Save(file_name.xml)сохраненный файл закодирован правильно, и если я загружу его в WideString (строка Unicode в Delphi) и передам его в веб-службу, все получится хорошо. Но как я могу сделать это, не сохраняя его на диск и через DOM?

3 ответа

Попробуйте явно передать Encoding.UTF8 в качестве второго параметра в конструкторе. См. http://msdn.microsoft.com/en-us/library/ms162588(v=VS.80).aspx

Вы пытались использовать метод setOption(SXH_OPTION_URL_CODEPAGE,Encoding.UTF8) на корневом узле, прежде чем получить доступ к XML?

РЕДАКТИРОВАТЬ: Теперь я понимаю вопрос лучше. Вы должны правильно установить кодировку, когда вы ЗАПИШИТЕ строку xml. Это очень распространенная проблема: установка кодировки в заголовке XML фактически не приводит к тому, что выходные данные соответствуют заявленной кодировке. Вы должны сконфигурировать модуль записи (или любой другой объект, записывающий поток вывода) для фактического создания UTF8.

Я ответил на аналогичный вопрос здесь.

В MSXML при сохранении файла будет также записана кодировка. Тем не менее, когда вы используете xml Свойство кодировка не будет включена. Это было сделано намеренно. Они разработали его таким образом, чтобы вы могли развернуться и вызвать LoadXml для строки, и это будет работать. Если кодировка была включена, вы получите ошибку Switch from current encoding to specified encoding not supported, Попробуйте сохранить документ, вызвав метод Save. Вы увидите, что кодировка включена.

ОБНОВИТЬ:

Я не в том месте, где я могу это проверить, но метод Save может принимать несколько типов параметров. Один из них является объектом, который реализует интерфейс IStream. В качестве такового вы можете использовать объект ADODB.Stream. Я не знаю Delphi, поэтому я напишу шаги, которые нужно предпринять.

  • Создайте экземпляр объекта ADODB.Stream
  • Установите для его свойства CharSet значение "utf-8". По умолчанию используется utf-16
  • Вызовите IXMLDOMDocument. Сохраните объект oject в качестве параметра.
  • Сбросьте Позиции потоков к 0, и установите его Тип к adTypeText
  • Вызовите ReadText для объекта потока, чтобы вернуть XML в виде строки
Другие вопросы по тегам