[英]C# openxml removal of paragraph
我試圖使用OpenXML從.docx文件中刪除段落(我使用一些占位符文本從docx模板類文件生成),但每當我刪除段落時,它都會破壞我用來迭代的foreach循環。
MainDocumentPart mainpart = doc.MainDocumentPart;
IEnumerable<OpenXmlElement> elems = mainPart.Document.Body.Descendants();
foreach(OpenXmlElement elem in elems){
if(elem is Text && elem.InnerText == "##MY_PLACE_HOLDER##")
{
Run run = (Run)elem.Parent;
Paragraph p = (Paragraph)run.Parent;
p.RemoveAllChildren();
p.Remove();
}
}
這工作,刪除我的占位符和它所在的段落, 但foreach循環停止迭代 。 在foreach循環中我需要做更多的事情。
這是使用的OpenXML和為什么我的foreach循環停止或如何使它不能停下來取消C#段確定方法是什么? 謝謝。
這是“萬聖節問題”,之所以這么稱呼,是因為一些開發人員在萬聖節時就注意到了這一點,看起來它們看起來很怪異。 這是使用聲明性代碼(查詢)同時使用命令式代碼(刪除節點)的問題。 如果你考慮一下,你正在迭代一個鏈表,如果你開始刪除鏈表中的節點,你就完全弄亂了迭代器。 避免此問題的一種更簡單的方法是在列表中“實現”查詢結果,然后您可以遍歷列表,並隨意刪除節點。 以下代碼的唯一區別是它在調用Descendants軸后調用ToList。
MainDocumentPart mainpart = doc.MainDocumentPart;
IEnumerable<OpenXmlElement> elems = mainPart.Document.Body.Descendants().ToList();
foreach(OpenXmlElement elem in elems){
if(elem is Text && elem.InnerText == "##MY_PLACE_HOLDER##")
{
Run run = (Run)elem.Parent;
Paragraph p = (Paragraph)run.Parent;
p.RemoveAllChildren();
p.Remove();
}
}
但是,我必須注意,我在您的代碼中看到了另一個錯誤。 沒有什么可以阻止Word將該文本節點從多個運行拆分為多個文本元素。 雖然在大多數情況下,您的代碼可以正常工作,但是您或用戶遲早會采取某些操作(例如選擇一個字符,並且不小心點擊功能區上的粗體按鈕),然后您的代碼將不再有效。
如果你真的想在文本級別工作,那么你需要使用代碼,比如我在這個屏幕上演示的代碼: http : //openxmldeveloper.org/blog/b/openxmldeveloper/archive/2011/08/04/引入-textreplacer-A-新級換電動工具換開xml.aspx
事實上,我相信你可能會逐字地使用該代碼來處理你的用例。
另一種更靈活,更強大的方法詳述如下:
雖然該screen-cast是關於PresentationML的,但同樣的原則適用於WordprocessingML。
但是,鑒於您使用的是WordprocessingML,更好的方法是使用內容控件。 有關文檔生成的一種方法,請參閱:
http://ericwhite.com/blog/map/generating-open-xml-wordprocessingml-documents-blog-post-series/
有關一般使用內容控件的大量信息,請參閱:
http://www.ericwhite.com/blog/content-controls-expanded
-Eric
首先必須使用兩個循環來存儲要刪除的項目,然后再刪除項目。 這樣的事情:
List<Paragraph> paragraphsToDelete = new List<Paragraph>();
foreach(OpenXmlElement elem in elems){
if(elem is Text && elem.InnerText == "##MY_PLACE_HOLDER##")
{
Run run = (Run)elem.Parent;
Paragraph p = (Paragraph)run.Parent;
paragraphsToDelete.Add(p);
}
}
foreach (var p in paragraphsToDelete)
{
p.RemoveAllChildren();
p.Remove();
}
Dim elems As IEnumerable(Of OpenXmlElement) = MainPart.Document.Body.Descendants().ToList()
For Each elem As OpenXmlElement In elems
If elem.InnerText.IndexOf("fullname") > 0 Then
elem.RemoveAllChildren()
End If
Next
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.