Слово OpenXML. Обход OpenXmlElements между закладками

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

Если вы нарисуете древовидную структуру документа, я бы хотел проверить все узлы между начальной и конечной закладками. Я думаю, что алгоритм обхода несбалансированного дерева, начинающийся с узла x и заканчивающийся узлом y, будет работать. Это звучит осуществимо или я что-то упустил.

Если это возможно, не могли бы вы указать мне направление обхода дерева, которое могло бы выполнить возврат узлов?


person user166244    schedule 11.11.2009    source источник


Ответы (2)


Это зависит от того, что вы хотите сделать, однако, если вас в первую очередь интересует текст между двумя закладками, то это один из тех случаев, когда семантику XmlDocument/Xpath использовать проще, чем LINQ to XML или строго типизированную объектную модель. Open XML SDK версии 2. Семантика оси XPath "following::*" - это то, что вам нужно. В следующем примере используются XmlDocument и XPath для печати имен узлов между началом и концом закладки.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

class Program
{
    public static XmlDocument GetXmlDocument(OpenXmlPart part)
    {
        XmlDocument xmlDoc = new XmlDocument();
        using (Stream partStream = part.GetStream())
        using (XmlReader partXmlReader = XmlReader.Create(partStream))
            xmlDoc.Load(partXmlReader);
        return xmlDoc;
    }

    static void Main(string[] args)
    {
        using (WordprocessingDocument doc =
            WordprocessingDocument.Open("Test.docx", false))
        {
            XmlDocument xmlDoc = GetXmlDocument(doc.MainDocumentPart);
            string wordNamespace =
                "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
            XmlNamespaceManager nsmgr =
                new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("w", wordNamespace);
            XmlElement bookmarkStart = (XmlElement)xmlDoc.SelectSingleNode("descendant::w:bookmarkStart[@w:id='0']", nsmgr);
            XmlNodeList nodesFollowing = bookmarkStart.SelectNodes("following::*", nsmgr);
            var nodesBetween = nodesFollowing
                .Cast<XmlNode>()
                .TakeWhile(n =>
                    {
                        if (n.Name != "w:bookmarkEnd")
                            return true;
                        if (n.Attributes.Cast<XmlAttribute>().Any(a => a.Name == "w:id" && a.Value == "0"))
                            return false;
                        return true;
                    });
            foreach (XmlElement item in nodesBetween)
            {
                Console.WriteLine(item.Name);
                if (item.Name == "w:bookmarkStart" || item.Name == "w:bookmarkEnd")
                    foreach (XmlAttribute att in item.Attributes)
                        Console.WriteLine("{0}:{1}", att.Name, att.Value);
            }
        }
    }
}
person Eric White    schedule 15.05.2011

Я составил алгоритм, который может легко получить текст закладки.

Как извлечь текст закладки из документа OpenXML WordprocessingML

Я также написал код для замены текста закладки:

Замена текста закладки в документе OpenXML WordprocessingML

-Эрик

person Eric White    schedule 09.09.2011
comment
Я думаю, что эти ссылки мертвы. - person James Toomey; 19.05.2020
comment
Они мертвы. Ошибки SQL-сервера. Вот почему хорошие ответы никогда не бывают просто ссылками. - person james.garriss; 17.06.2021