2015-02-09 66 views
0

在XML中取消註釋某個節點主體的最簡單方法是什麼?該元素具有唯一的名稱,該文件的結構如下所示:使用C#中的Xml文檔取消註釋XML片段#

somefile.xml

<?xml version="1.0"?> 
<name1> 
    <irrelevant1> 
    <irrelevant2> 
    <!-- 
     <irrelevant3 /> 
    --> 
    </irrelevant2> 
    </irrelevant1> 
    <name2> 
    <name3> 
    <!-- 
     <name4 field="The" /> 
     <name4 field="Owls" /> 
     <name4 field="Are /> 
     <name4 field="Not" /> 
     <name4 field="What" /> 
     <name4 field="They" /> 
     <name4 field="Seem /> 
    --> 
    </name3> 
    </name2> 
</name1> 

我們的目標應該是這樣的,去掉註釋:

uncommented.xml

<?xml version="1.0"?> 
<name1> 
    <irrelevant1> 
    <irrelevant2> 
    <!-- 
     <irrelevant3 /> 
    --> 
    </irrelevant2> 
    </irrelevant1> 
    <name2> 
    <name3> 
     <name4 field="The" /> 
     <name4 field="Owls" /> 
     <name4 field="Are /> 
     <name4 field="Not" /> 
     <name4 field="What" /> 
     <name4 field="They" /> 
     <name4 field="Seem /> 
    </name3> 
    </name2> 
</name1> 

我的解析方法:

XmlDocument xdoc = new XmlDocument(); 
xdoc.Load(@"C:\somefile.xml"); 

XmlNodeList nl = xdoc.GetElementsByTagName("name2"); 

XmlNode xn = nl[0]; 
string xn_content = xn.InnerXml; 

xn_content = Regex.Replace(xn_content, "<!--|-->", String.Empty); 

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xn_content); 
XmlNode newNode = doc.DocumentElement; 

// this import doesn't really help 
xdoc.ImportNode(newNode, true); 
xn.RemoveAll(); 
xn.AppendChild(newNode); 

xdoc.Save(@"C:\uncommented.xml"); 

結果與ArgumentException的:

{「要插入的節點是從不同的文檔內容。」}

+0

你打算使用Linq到XML(XDocument)嗎? – 2015-02-09 22:14:32

+0

爲什麼** irrelevant3 **不是沒有完美的。 'irrelevant2'和'name3'的規則是什麼?爲什麼只有'name3'的孩子沒有註釋?我們如何區分它們的程式化? – EZI 2015-02-09 22:19:21

+0

你缺少關於''的結束引號,它應該是''還有''。 – dbc 2015-02-10 02:18:03

回答

1

你眼前的問題是,你叫XmlDocument.ImportNode()但不要使用返回節點。你需要做newNode = xDoc.ImportNode(newNode, true);

但是,更簡單的方法是避免完全解析Regex。相反,下降的XmlNode層次,挑選出你希望取消對XmlComment節點,加載其InnerTextXmlDocumentFragment,那麼它的新創建的兒童增加了評論的父節點:

public static class XmlNodeExtensions 
{ 
    public static XmlDocument Document(this XmlNode node) 
    { 
     for (; node != null; node = node.ParentNode) 
     { 
      var doc = node as XmlDocument; 
      if (doc != null) 
       return doc; 
     } 
     return null; 
    } 

    public static IEnumerable<XmlNode> AncestorsAndSelf(this XmlNode node) 
    { 
     for (; node != null; node = node.ParentNode) 
      yield return node; 
    } 

    public static IEnumerable<XmlNode> DescendantsAndSelf(this XmlNode root) 
    { 
     if (root == null) 
      yield break; 
     yield return root; 
     foreach (var child in root.ChildNodes.Cast<XmlNode>()) 
      foreach (var subChild in child.DescendantsAndSelf()) 
       yield return subChild; 
    } 

    public static void UncommentXmlNodes(IEnumerable<XmlComment> comments) 
    { 
     foreach (var comment in comments.ToList()) 
      UncommentXmlNode(comment); 
    } 

    public static void UncommentXmlNode(XmlComment comment) 
    { 
     if (comment == null) 
      throw new NullReferenceException(); 
     var doc = comment.Document(); 
     if (doc == null) 
      throw new InvalidOperationException(); 
     var parent = comment.ParentNode; 
     var innerText = comment.InnerText; 
     XmlDocumentFragment docFrag = doc.CreateDocumentFragment(); 
     //Set the contents of the document fragment. 
     docFrag.InnerXml = innerText; 
     XmlNode insertAfter = comment; 
     foreach (var child in docFrag.ChildNodes.OfType<XmlElement>().ToList()) 
     { 
      insertAfter = parent.InsertAfter(child, insertAfter); 
     } 
     parent.RemoveChild(comment); 
    } 
} 

然後調用它像:

 string xml = @"<?xml version=""1.0""?> 
     <name1> 
      <irrelevant1> 
      <irrelevant2> 
      <!-- 
       <irrelevant3 /> 
      --> 
      </irrelevant2> 
      </irrelevant1> 
      <name2> 
      <name3> 
      <!-- 
       <name4 field=""The"" /> 
       <name4 field=""Owls"" /> 
       <name4 field=""Are"" /> 
       <name4 field=""Not"" /> 
       <name4 field=""What"" /> 
       <name4 field=""They"" /> 
       <name4 field=""Seem"" /> 
      --> 
      </name3> 
      </name2> 
     </name1> 
     "; 
     var xmlDoc = new XmlDocument(); 
     xmlDoc.LoadXml(xml); 
     Debug.WriteLine(xmlDoc.ToXml()); 

     XmlNodeExtensions.UncommentXmlNodes(xmlDoc.DocumentElement.DescendantsAndSelf().OfType<XmlComment>().Where(c => c.ParentNode.Name == "name3")); 

     Debug.WriteLine(xmlDoc.ToXml()); 

請注意,您評論的XML無效。 <name4 field="Are />應該是<name4 field="Are"/><name4 field="Seem />應該是<name4 field="Seem"/>。我在測試用例中爲你解決了這個問題,因爲我認爲它是一個錯字。