[英]Powerpoint OpenXML whitespace is disappearing
我遇到一個問題,一旦我引用幻燈片,就會在powerpoint文檔中刪除空格。 以下代碼示例說明了我的意思 -
//Open the document.
using(PresentationDocument presentationDocument = PresentationDocument.Open(pptxFileName, true))
{
//Just making this reference modifies the whitespace in the slide.
Slide slide = presentationDocument.PresentationPart.SlideParts.First().Slide;
}
要重現此問題,請使用單個幻燈片創建演示文稿,其中包含單個文本框,其中包含文本“[]”(無引號)。 現在,將方括號之間的空格字體設置為與文本其余部分不同的顏色。 這將導致Run僅包含空格字符。 一旦上面的代碼針對此演示文稿運行,引用幻燈片的行將導致運行中的空白消失,最終使我們的視覺更改演示文稿比我們最初開始時,即使我們從未明確更改任何內容 - 在powerpoint應用程序中打開時,文本現在將為“[]”。
在Word中,可以將xml:space屬性設置為“保留”文本元素以保留空格,但似乎沒有Powerpoint的等效項。
在將空白用作幻燈片設計的關鍵組件的情況下,這是一個關鍵問題。 有沒有人找到解決這個問題的方法?
是的,您在SDK中發現了一個錯誤。
@Chris,首先,根據Open XML SDK的語義,該代碼是修改文件的。 當您訪問部件的內容,然后超出using語句的范圍時,部件的內容將寫回到包中。 這是因為為讀/寫(調用Open方法的第二個參數)打開了演示文稿。
問題是當從包中讀取部件的內容時,空間被剝離。
//Open the document.
using (PresentationDocument presentationDocument = PresentationDocument.Open("test.pptx", true))
{
//Just making this reference modifies the whitespace in the slide.
Slide slide = presentationDocument.PresentationPart.SlideParts.First().Slide;
var sh = slide.CommonSlideData.ShapeTree.Elements<DocumentFormat.OpenXml.Presentation.Shape>().First();
Run r = sh.TextBody.Elements<Paragraph>().First().Elements<Run>().Skip(1).FirstOrDefault();
Console.WriteLine(">{0}<", r.Text.Text);
//r.Text.Text = " ";
}
如果在演示文稿上運行上述代碼,則可以看到,當您訪問該文本元素時,文本元素的文本已經不正確。
如果取消注釋設置文本的行,有趣的是,幻燈片確實包含空格。
這顯然是一個錯誤。 我已向負責Open XML SDK的Microsoft程序經理報告。
由於這種情況對您很重要,我建議您使用LINQ to XML代碼。 以下代碼工作正常:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Drawing;
public static class PtOpenXmlExtensions
{
public static XDocument GetXDocument(this OpenXmlPart part)
{
XDocument partXDocument = part.Annotation<XDocument>();
if (partXDocument != null)
return partXDocument;
using (Stream partStream = part.GetStream())
using (XmlReader partXmlReader = XmlReader.Create(partStream))
partXDocument = XDocument.Load(partXmlReader);
part.AddAnnotation(partXDocument);
return partXDocument;
}
public static void PutXDocument(this OpenXmlPart part)
{
XDocument partXDocument = part.GetXDocument();
if (partXDocument != null)
{
using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write))
using (XmlWriter partXmlWriter = XmlWriter.Create(partStream))
partXDocument.Save(partXmlWriter);
}
}
}
class Program
{
static void Main(string[] args)
{
using (PresentationDocument presentationDocument = PresentationDocument.Open("test.pptx", true))
{
XDocument slideXDoc = presentationDocument.PresentationPart.SlideParts.First().GetXDocument();
XNamespace p = "http://schemas.openxmlformats.org/presentationml/2006/main";
XNamespace a = "http://schemas.openxmlformats.org/drawingml/2006/main";
XElement sh = slideXDoc.Root.Element(p + "cSld").Element(p + "spTree").Elements(p + "sp").First();
XElement r = sh.Element(p + "txBody").Elements(a + "p").Elements(a + "r").Skip(1).FirstOrDefault();
Console.WriteLine(">{0}<", r.Element(a + "t").Value);
}
}
}
理論上,您可以編寫一些通用代碼來挖掘LINQ to XML樹,查找僅包含重要空白區域的所有元素,然后遍歷Open XML SDK元素樹,並設置這些元素的文本。 這有點亂,但一旦完成,您可以使用Open XML SDK 2.0的強類型OM。 這些元素的值將是正確的。
使用Open XML更容易使用LINQ to XML的一種技術是對XName對象進行preatomization。 見http://blogs.msdn.com/b/ericwhite/archive/2008/12/15/a-more-robust-approach-for-handling-xname-objects-in-linq-to-xml.aspx
-Eric
Open XML SDK 2.5已更正此問題
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.