2009-11-11 5 views
4

북마크 시작과 북마크 종료 태그 사이를 노드를 통과해야합니다. 문제는 트리 탐색으로 나뉘는 것처럼 보이지만 올바른 알고리즘을 고정하는 데 문제가 있습니다. 책갈피 시작 및 끝 요소는 비 합성 노드 (자식 없음)이며 트리의 임의의 깊이에 나타날 수 있습니다. 북마크 시작은 같은 깊이로 보장되지 않습니다.Word OpenXML. 북마크간에 OpenXmlElements 이동하기

문서의 트리 구조를 그리면 시작 및 끝 책갈피 사이의 모든 노드를 검사하려고합니다. 노드 x에서 시작하여 노드 y에서 끝나는 불균형 트리를 가로 지르는 알고리즘이 효과가 있다고 생각합니다. 이것이 실현 가능하게 들리거나 나는 뭔가를 놓친다.

가능하다면 노드를 반환 할 수있는 트리 탐색 방향으로 나를 가리킬 수 있습니까?

답변

2

두 가지 책갈피 사이의 텍스트에 주로 관심이있는 경우이 작업은 사용자가 원하는 작업에 따라 다르지만 LINQ to XML이나 강력하게 XmlDocument/XPath 의미를 사용하는 것이 더 쉬운 경우 중 하나입니다 Open XML SDK V2의 형식화 된 개체 모델입니다. 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); 
      } 
     } 
    } 
}