Word OpenXML. Moving OpenXmlElements between bookmarks

I need to cross the nodes between the start of the bookmark and the end tag of the bookmark. The problem seems to break down around the tree, but I am having problems installing the correct algorithm. Elements of the initial and final bookmarks are composite nodes (without children) and can be displayed at an arbitrary depth in the tree. Bookmark launch is also not guaranteed at the same depth.

If you are drawing a tree structure for a document, I would like to examine all the nodes between the start and end bookmarks. I think that an algorithm for moving an asymmetric tree starting with node x and ending with node y will work. It sounds doable or something is missing.

If possible, can you tell me the tree traversal direction that could return nodes?

+4
source share
2 answers

It depends on what you want to do, however, if you are primarily interested in the text between the two tabs, then this is one of the cases when the semantics of XmlDocument / XPath are easier to use than LINQ to XML, a typed Open XML object model SDK V2. The semantics of the "next :: *" XPath axis are what you want. The following example uses XmlDocument and XPath to print node names between the beginning and end of a bookmark.

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); } } } } 
+2
source

I put together an algorithm that can easily get bookmark text.

How to get bookmark text from an OpenXML WordprocessingML document

I also wrote code to replace the bookmark text:

Replacing bookmark text in an OpenXML WordprocessingML document

Eric

+2
source

Source: https://habr.com/ru/post/924055/


All Articles