Слово OpenXML. Обход OpenXmlElements между закладками - PullRequest
4 голосов
/ 12 ноября 2009

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

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

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

Ответы [ 2 ]

2 голосов
/ 09 сентября 2011

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

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

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

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

-Эрик

2 голосов
/ 15 мая 2011

Это зависит от того, что вы хотите сделать, однако, если вас в первую очередь интересует текст между двумя закладками, то это один из тех случаев, когда семантику XmlDocument / XPath легче использовать, чем LINQ to XML или сильно типизированная объектная модель Open XML SDK V2. Семантика оси XPath 'следующим :: *' - это то, что вам нужно. В следующем примере 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);
            }
        }
    }
}
...