XmlWriter - запись из ридера (фрагмент xml)

Можно ли скопировать весь контент (фрагмент xml) из одного потока (используя xmlReader) во второй (xmlWriter).

У меня есть несколько процедур, которые возвращают фрагменты xml.

<item></item>
<item></item>
<item></item>
<item></item>
<item></item>

using (XmlWriter writer = XmlWriter.Create(stream, _settings))
{
    writer.WriteStartElement(typeName);
    writer.WriteAttributeString("RowVersion", rowVersion);
    for (int i = 1; i <= packagesCount; i++)
    {
         cmd.Parameters["@packageNumber"].Value = i;
         using (var r = cmd.ExecuteXmlReader())
         {
              //need copy all fragment from reader
         }
                    writer.WriteEndElement();

                }
    }

Есть такой метод, как write.WriteNode(reader,true), но с его помощью мне нужно перебрать все элементы. Это неэффективно, когда у меня 10000 элементов в одном фрагменте. Мне нужно просто скопировать весь контент. Кроме того, этот фрагмент может быть очень большим, поэтому я предпочитаю использовать поток, а не сохранять его в строке.


person adamo94    schedule 11.03.2016    source источник
comment
Вы пробовали класс XDocument? msdn.microsoft.com /en-us/библиотека/   -  person Soundararajan    schedule 11.03.2016
comment
Конечно, я могу сделать это с помощью XDocument - XDocument.Load(XmlReader) и XDocument.WriteTo(XmlWriter), но с помощью этого метода мне нужно сохранить весь этот фрагмент в экземпляре XDocoment.   -  person adamo94    schedule 11.03.2016


Ответы (1)


Старый пост, но может кому пригодится.

Мне приходится иметь дело с довольно большими файлами XML (> 50 МБ). И мне нужно извлечь из них сегмент и работать с этими сегментами отдельно. Итак, я сделал это:

  class Program
  {

    static void processXML(string xml)
    {

      SqlServerTypes.Utilities.LoadNativeAssemblies(AppDomain.CurrentDomain.BaseDirectory);

      XmlReader reader = XmlReader.Create(xml);

      XmlWriterSettings settings = new XmlWriterSettings
      {
        ConformanceLevel = ConformanceLevel.Auto
      };
      var output_file = "output.xml";

      if (File.Exists(output_file))
      {
        File.Delete(output_file);
      }

      XmlWriter writer = XmlWriter.Create("output.xml", settings);
      try
      {

        Console.WriteLine("Processing: " + xml);
        Console.WriteLine("Outputting to: " + Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "output.xml"));
        //extract all namespaces used in document
        XPathDocument x = new XPathDocument(reader);
        XPathNavigator foo = x.CreateNavigator();
        foo.MoveToFollowing(XPathNodeType.Element);
        IDictionary<string, string> Namespaces = foo.GetNamespacesInScope(XmlNamespaceScope.All);

        reader = XmlReader.Create(xml);
        var elementFullName_ = "";
        var elementName_ = "";
        var elementToFind = "sl:stand";
        var elementsFound = 0;
        var prefix_ = "";
        var text_ = "";
        var whiteSpace_ = "";
        while (reader.Read())
        {
          switch (reader.NodeType)
          {
            case XmlNodeType.Element:
              elementFullName_ = reader.Name;
              if (elementFullName_ == elementToFind)
              {
                //avoid processing the file if XmlWriter just started
                if (writer.WriteState != WriteState.Start)
                {
                  writer.Flush();
                  writer.Close();
                  //here process the file for whatever you want
                  if (File.Exists(output_file))
                  {
                    File.Delete(output_file);
                  }
                  writer = XmlWriter.Create("output.xml", settings);
                }
                elementsFound = 1;
              }
              else if(elementsFound > 0)
              {
                elementsFound++;
              }
              var arr = reader.Name.Split(':');
              if (arr.Length == 2)
              {
                prefix_ = arr[0];
                elementName_ = arr[1];
                if (elementsFound > 0)
                  writer.WriteStartElement(arr[0], arr[1], Namespaces[arr[0]]);
              }
              else
              {
                prefix_ = "";
                elementName_ = reader.Name;
                if (elementsFound > 0)
                  writer.WriteStartElement(reader.Name);
              }

              if (elementsFound > 0 && reader.HasAttributes)
                writer.WriteAttributes(reader, true);

              if (elementsFound > 0 && reader.IsEmptyElement)
                writer.WriteEndElement();

              break;
            case XmlNodeType.EndElement:

              if (elementsFound > 0)
              {
                writer.WriteEndElement();
              }

              if (elementsFound > 0)
              {
                elementsFound--;
              }

              if (elementsFound == 0)
              {
              }

              break;
            case XmlNodeType.Text:
              if (elementFullName_ == "gml:posList")
              {
                text_ = reader.Value;
              }
              if (elementsFound > 0)
                writer.WriteString(reader.Value);
              break;
            case XmlNodeType.Whitespace:
              if (elementFullName_ == "gml:posList")
              {
                whiteSpace_ = reader.Value;
              }
              if (elementsFound > 0)
                writer.WriteWhitespace(reader.Value);
              break;
          }
        }

      }
      finally
      {
        reader.Close();
        writer.Close();
      }
    }
    static void Main(string[] args)
    {

      var xml = "";


      if (args.Length == 0 || !File.Exists(args[0]))
      {
        Console.WriteLine("Please, provide a valid XML file as a commandline parameter");
        return;
      }

      xml = args[0];

      processXML(xml);

      Console.WriteLine("Done!");
    }
  }

Примечание: некоторые условия не важны для вас, поэтому вы можете их удалить.

person Dejan Dozet    schedule 16.04.2021