Создать XML для Excel с помощью LINQ to XML

118
06 февраля 2021, 05:10

Пытаюсь построить XML для Excel такого вида:

<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
          xmlns:o="urn:schemas-microsoft-com:office:office" 
          xmlns:x="urn:schemas-microsoft-com:office:excel" 
          xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
          xmlns:html="http://www.w3.org/TR/REC-html40">
 <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
  <Author>OOO XXX</Author>
  <LastAuthor>Nickolay Efimov</LastAuthor>
  <Created>2018-03-20T06:19:09Z</Created>
 </DocumentProperties>
</Workbook>

Мой код на C#:

    XElement Workbook = new XElement(xmlns + "Workbook",
                    new XAttribute("xmlns", "urn:schemas-microsoft-com:office:spreadsheet"),
                    new XAttribute(XNamespace.Xmlns + "o", "urn:schemas-microsoft-com:office:office"),
                    new XAttribute(XNamespace.Xmlns + "x", "urn:schemas-microsoft-com:office:excel"),
                    new XAttribute(XNamespace.Xmlns + "ss", "urn:schemas-microsoft-com:office:spreadsheet"),
                    new XAttribute(XNamespace.Xmlns + "html", "http://www.w3.org/TR/REC-html40"),
                    new XElement(xmlnsO + "DocumentProperties",
                        new XAttribute("xmlns", "urn:schemas-microsoft-com:office:office"), 
                        new XElement("Author", "OOO XXX"),
                        new XElement("LastAuthor", "Nickolay Efimov"), 
                        new XElement("Created", "2018-03-20T06:19:09Z")));

Выходной XML получается такой:

<ss:Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
             xmlns:o="urn:schemas-microsoft-com:office:office" 
             xmlns:x="urn:schemas-microsoft-com:office:excel" 
             xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
             xmlns:html="http://www.w3.org/TR/REC-html40">
  <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
    <Author xmlns="">OOO XXX</Author>
    <LastAuthor xmlns="">Nickolay Efimov</LastAuthor>
    <Created xmlns="">2018-03-20T06:19:09Z</Created>
  </DocumentProperties>
</ss:Workbook>

Не могу понять почему появляется ss у Workbook и откуда берутся xmlns="" у дочерних элементов DocumentProperties

Answer 1

Атрибут типа xmlns или xmlns:prefix имеет особое значение: это указание пространства имён. Его не нужно задавать самостоятельно как XAttribute.

Нужно создать переменные типа XNamespace и добавлять их к именам элементов.
Закомментированы неймспейсы, которые непосредственно в данном куске кода не участвуют.

XNamespace spreadsheet = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace office = "urn:schemas-microsoft-com:office:office";
//XNamespace excel = "urn:schemas-microsoft-com:office:excel";
//XNamespace html = "http://www.w3.org/TR/REC-html40";
var workbook = new XElement(spreadsheet + "Workbook",
    new XElement(office + "DocumentProperties",
        new XElement(office + "Author", "OOO XXX"),
        new XElement(office + "LastAuthor", "Nickolay Efimov"),
        new XElement(office + "Created", "2018-03-20T06:19:09Z")
        )
    );

Это даст xml следующего вида:

<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet">
  <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
    <Author>OOO XXX</Author>
    <LastAuthor>Nickolay Efimov</LastAuthor>
    <Created>2018-03-20T06:19:09Z</Created>
  </DocumentProperties>
</Workbook>

Наличие или отсутствие неймспейсов, которые реально не используются, не должно сказываться на валидации.

Если в xml имелись элементы с другими пространствами имён, то их определения добавились бы автоматически.

Если по какой-либо причине всё же нужно, чтобы в итоговом xml были определения неймспейсов, которых нет ни у одного узла, то их можно добавить, как это сделали вы.

XNamespace spreadsheet = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace office = "urn:schemas-microsoft-com:office:office";                
var workbook = new XElement(spreadsheet + "Workbook",
    new XAttribute(XNamespace.Xmlns + "o", "urn:schemas-microsoft-com:office:office"),
    new XAttribute(XNamespace.Xmlns + "x", "urn:schemas-microsoft-com:office:excel"),                    
    new XAttribute(XNamespace.Xmlns + "html", "http://www.w3.org/TR/REC-html40"),
    new XElement(office + "DocumentProperties",
        new XElement(office + "Author", "OOO XXX"),
        new XElement(office + "LastAuthor", "Nickolay Efimov"),
        new XElement(office + "Created", "2018-03-20T06:19:09Z")
        )
    );

Это даст xml следующего вида:

<Workbook xmlns:o="urn:schemas-microsoft-com:office:office"
          xmlns:x="urn:schemas-microsoft-com:office:excel"
          xmlns:html="http://www.w3.org/TR/REC-html40"
          xmlns="urn:schemas-microsoft-com:office:spreadsheet">
  <o:DocumentProperties>
    <o:Author>OOO XXX</o:Author>
    <o:LastAuthor>Nickolay Efimov</o:LastAuthor>
    <o:Created>2018-03-20T06:19:09Z</o:Created>
  </o:DocumentProperties>
</Workbook>

Весьма близко к желаемому, хотя и есть отличия. Но с точки зрения валидации, этот xml эквивалентен как предыдущему, так и тому, что приведён в вашем вопросе.

Порядок определения неймспейсов, как и порядок атрибутов, не важен в xml.
Префиксы пространств имён не имеют никакого значения.

Пространство имён может быть определено на любом уровне, как непосредственно у элемента, так и у любого из его предков выше по иерархии. Тут в элементе DocumentProperties нет определения, оно находится выше.

READ ALSO
не отображается библиотека к проекту C#

не отображается библиотека к проекту C#

Возникла проблема, не могу подключить библиотеку к своему проектуВ ссылках проекта она не появляется

92
Вытащить данные из TXT в datagridview. C#

Вытащить данные из TXT в datagridview. C#

Есть такой файл TXT (картинка ниже)Мне нужно как то сделать так, чтобы в базу DATAGRIDVIEW записывалась строка, у которой начало строки начинается...

137
Модернизация и плавная прокрутка ScrollViewer

Модернизация и плавная прокрутка ScrollViewer

Столкнулся с такой проблемойЕсть в xaml такая разметка:

113