【问题标题】:Generating a XML Excel document using XDocument使用 XDocument 生成 XML Excel 文档
【发布时间】:2021-12-07 17:16:22
【问题描述】:

我正在尝试生成这样的 XML Excel 文档

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<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">
 <Styles>
  <Style ss:ID="Default" /></Style>
 </Styles>
 <Worksheet ss:Name="Worksheet Name">
  <Table>
   <Row ss:AutoFitHeight="0">
    <Cell>
     <Data ss:Type="String">Test</Data>
    </Cell>
   </Row>
  </Table>
 </Worksheet>
</Workbook>

我目前的结果是这样的:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<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">
  <Styles xmlns="">
    <Style ss:ID="Default" />
  </Styles>
  <Worksheet ss:Name="Worksheet Name" xmlns="">
    <Table>
      <Row ss:AutoFitHeight="0">
        <Cell>
          <Data ss:Type="String">Test</Data>
        </Cell>
      </Row>
    </Table>
  </Worksheet>
</ss:Workbook>

我尝试了很多不同的解决方案,但没有任何运气。我需要用 Workbook 替换 ss:Workbook 并去掉所有的 xmlns=""。

我当前的代码如下所示(LinqPad):

void Main()
{
    XNamespace ss = "urn:schemas-microsoft-com:office:spreadsheet";
    XNamespace ns = "urn:schemas-microsoft-com:office:spreadsheet";

    var workbook = new XElement(ns + "Workbook");
    workbook.Add(new XAttribute("xmlns", "urn:schemas-microsoft-com:office:spreadsheet"));
    workbook.Add(new XAttribute(XNamespace.Xmlns + "o", "urn:schemas-microsoft-com:office:office"));
    workbook.Add(new XAttribute(XNamespace.Xmlns + "x", "urn:schemas-microsoft-com:office:excel"));
    workbook.Add(new XAttribute(XNamespace.Xmlns + "ss", "urn:schemas-microsoft-com:office:spreadsheet"));
    workbook.Add(new XAttribute(XNamespace.Xmlns + "html", "http://www.w3.org/TR/REC-html40"));

    var styles = new XElement("Styles");
    workbook.Add(styles);
    var style = new XElement("Style");
    style.Add(new XAttribute(ss + "ID", "Default"));
    styles.Add(style);

    var worksheet = new XElement("Worksheet");
    worksheet.Add(new XAttribute(ss + "Name", "Worksheet Name"));
    workbook.Add(worksheet);

    var table = new XElement("Table");
    worksheet.Add(table);

    var row = new XElement("Row");
    row.Add(new XAttribute(ss + "AutoFitHeight", 0));
    table.Add(row);

    var cell = new XElement("Cell");
    var data = new XElement("Data");
    data.Add(new XAttribute(ss + "Type", "String"));
    data.Value = "Test";
    cell.Add(data);
    row.Add(cell);

    var document = new XDocument(new XDeclaration("1.0", "", null));
    document.Add(new XProcessingInstruction("mso-application", "progid=\"Excel.Sheet\""));
    document.Add(workbook);

    var sw = new CustomStringWriter();
    document.Save(sw);
    sw.ToString().Dump();
    //sw.ToString().Replace("ss:Workbook", "Workbook").Replace("xmlns=\"\"", "").Dump();
}

// Define other methods and classes here

class CustomStringWriter : StringWriter
{
    public override Encoding Encoding
    {
        get
        {
            return null;
        }
    }
}

有什么建议吗?

【问题讨论】:

  • 目前我最好的 hack 是在添加 Workbook 元素而不添加 xmlns 命名空间时省略命名空间。将文档转换为字符串后,我手动将 xmlns 命名空间添加到 Workbook 元素。它不漂亮,但它有效。
  • 这是 stackoverflow.com/questions/12075157/… 的副本,建议的解决方案是使用 Open XML。不过,这不是我的首选解决方案...

标签: c# xml excel xelement


【解决方案1】:

您的问题很可能是您没有理解默认命名空间是从父元素继承的。以这个 XML 为例:

<parent xmlns="http://namespace.com/uri">
    <child />
</parent>

在此,child 也有命名空间http://namespace.com/uri

所以你的StyleWorksheet 元素等都有xmlns="" 的原因是因为你明确说这些没有命名空间。

您应该修改所有这些元素的创建以包含正确的命名空间,例如:

var styles = new XElement(ss + "Styles");

顺便说一句,我还注意到 LINQ to XML 支持的声明性方法比您目前采用的方法要多得多。您可以通过构造函数传递所有元素的内容。所以你可以重写你的样式:

var styles = new XElement(ss + "Styles",
    new XElement(ss + "Style",
        new XAttribute("ID", "Default")
        )
    );

请参阅this fiddle 以获取以这种风格修复和重写的示例。

【讨论】:

  • 我知道命名空间是继承的,这就是以 xmlns="" 结尾的原因。添加命名空间只能解决我的一半问题。现在我到处都有命名空间。我什至不希望它出现在 Workbook 元素上。因此,您的解决方案对我不起作用。我不是声明式方法的忠实拥护者,这就是我不使用它的原因 ;-) 代码示例是从更大类的 sn-ps 组合而成的。
  • 如果您指的是前缀,则由于 LINQ to XML 在编写 XML 时的工作方式,您无法删除这些前缀。例如,请参阅 this fiddle - 只需解析和编写您的“必需”XML 即可将 ss 前缀添加到该命名空间中的所有元素。但是,请确保两者在语义上是相同的。
  • 如果您重新订购以将默认命名空间放在重复的 ss 前缀之后,则 LINQ to XML 命名空间查找元素将首先到达该名称空间并使用它(请参阅this fiddle)。如果您更喜欢它的外观,那会让您更接近。我只能强调所有 3 种表示在语义上都是相同的。
  • 我真的不在乎它的外观 - 我在乎 Excel 是否接受 XML :-) Excel 接受你第二把小提琴的结果。我想我会选择那个,或者只是手动将 xmlsns 插入根目录。尚未决定,但感谢您的帮助。
【解决方案2】:

我遇到了同样的问题,这是我的解决方案

您是否生成了 SAP 值映射模板文件?

            var xmlstr="<Workbook...."
            var xdoc = XDocument.Parse(xmlstr);
            using (TextWriter writer = new StringWriter())
            {
                xdoc.Save(writer);
                var output = writer.ToString();
                // replace default namespace prefix:<ss:
                string result = Regex.Replace(Regex.Replace(output, "<ss:", "<"), "</ss:", "</");
                return Encoding.UTF8.GetBytes(result);
            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 2010-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多