【问题标题】:How OpenXmlReader.Skip supposed to work?OpenXmlReader.Skip 应该如何工作?
【发布时间】:2016-02-05 17:38:38
【问题描述】:

来自documentation

跳过当前节点的子元素

代码如下:

var reader = DocumentFormat.OpenXml.OpenXmlReader.Create(worksheetPart);

// Header
while (reader.Read())
{
    if (reader.ElementType == typeof (Row)) // reader is at row r="1"
    {
        headers = GetHeaders((Row)reader.LoadCurrentElement(), _doc.WorkbookPart);
        reader.ReadNextSibling(); // reader is at row r="2"
        break;
    }
}

//...
reader.Skip(); // reader is at row r="3"

工作表 xml(剪切):

<x:sheetData xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:row r="1" spans="1:1">
      <x:c r="A1" s="1" t="s">
        <x:v>36</x:v>
      </x:c>
  </x:row>
  <x:row r="2" spans="1:1"> <!-- before calling Skip reader is here -->
      <x:c r="A2" s="1" t="s">
        <x:v>38</x:v>
      </x:c>
  </x:row> <!-- I expect reader to be here after calling Skip because closing tag != child element -->
  <x:row r="3" spans="1:1"> <!-- after calling Skip reader goes here -->
      <x:c r="A3" s="1" t="s">
        <x:v>38</x:v>
      </x:c>
  </x:row>
</x:sheetData>

为什么Skip 也跳过&lt;/x:row&gt;

【问题讨论】:

    标签: c# xml openxml xlsx xmlreader


    【解决方案1】:

    &lt;x:row&gt; 是 XML 文件中 一个 元素的开始标记(标记开始),&lt;/x:row&gt; 是结束标记(标记结束)。

    当您解析 XML 文档时,它表示为节点对象树,每个节点都有父节点、兄弟节点和子节点。

    所以不要将内存中的树表示与文件表示混淆。

    【讨论】:

    • 感谢您的澄清,但无论如何我认为这是错误的或至少令人困惑,需要更新文档。例如OpenXmlReader.Read(根据文档移动以读取下一个元素)它还读取 end tags 从中我可以得出结论,结束标签被视为不应跳过的单独元素,因为它不是孩子,OpenXmlReader.LoadCurrentElement 也将阅读器移动到结束标记。我认为 Skip 应该是一致的,它应该让读者在结束标签上保持一致。你不同意吗?
    • @Vladimir 是的,这可能会令人困惑。 Javas XMLStreamReader 例如开始标签和结束标签上的位置,即将它们视为单独的位置,而OpenXMLReader 对元素而不是标签进行操作
    【解决方案2】:

    这是一个小扩展方法,可以跳过 T 类型元素的下一个标签。标签可以是开始标签或结束标签。 (注意:如果没有该类型的标签,则会跳到文档的末尾)

    public static void SkipTo<T>(this OpenXmlReader reader) where T : OpenXmlElement
    {
        while (reader.Read() && reader.ElementType != typeof(T))
            ;
    }
    

    通常在阅读时您知道当前元素的类型:

    if (reader.ElementType == typeof(PivotFields) && !reader.IsEndElement)
    {
        // some code ...
        reader.SkipTo<PivotFields>(); // reader is now at </x:pivotFields>
        // some code ...
    }
    

    【讨论】:

      猜你喜欢
      • 2016-02-16
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 2017-01-14
      • 2013-05-04
      相关资源
      最近更新 更多