因此,我正在编写一个pptx解析器,并使用OpenXML来加载数据。一切都很好(这是一个谎言-我实际上已经准备好将计算机扔到整个房间并跳出窗口),但是我在加载我根本无法弄清的视频时遇到了问题。问题是OpenXML似乎无法找到指定视频URI的关系标签。
我所做的是编写代码来循环浏览幻灯片中的各个部分并注销其ID,如下所示:
SlidePart slidePart = ...;
foreach(var curPart in slidePart.Parts)
Console.WriteLine("Part ID: " + curPart.RelationshipId);
所以效果很好-它注销了slide.xml.rels文件中指定的所有关系-除了相关文件的视频关系之外。我可以在rels文件中看到视频关系,它与幻灯片中videoFile标签的链接ID匹配,但是我不知道如何通过代码来实现。我的图像加载正常(OpenXML可以找到图像关系)。视频关系与其他关系是否有区别?如何获得视频URI?
视频版本存储在SlidePart的ExternalReleationships集合中。
Powerpoint通过以下方式(简化)将视频(外部文件)嵌入到演示文稿中:
Video
)标签内创建一个p:video(类别Timing
)标签,包含视频的幻灯片。p:video标记包含一个名为p:cMediaNode(类别CommonMediaNode
)的子代。
p:cMediaNode包含一个名为p:tgtEl的孩子(类TargetElement
。
同样,p:cMediaNode包含一个称为p:spTgt的子代(类ShapeTarget
),指向与视频相关的图片形状的ID。图片ID形状存储在NonVisualDrawingProperties
Id
成员中。因此,视频通过这些ID连接到图片形状。
此外,图片形状包含一个称为a:videoFile的子类(类VideoFromFile
)。VideoFromFile类具有一个名为Link
的成员,该成员指向Id的ID。外部关系。
我强烈建议您下载OpenXML SDK 2.0生产率工具。这个工具允许您检查演示文稿文件的生成的XML。
以下代码列举了给定演示文稿中所有幻灯片的所有视频。对于每个视频,将打印到外部文件的Uri。这是通过找到给定视频的外部外部联系。
using (var doc = PresentationDocument.Open("c:\\temp\\presentation.pptx", false))
{
var presentation = doc.PresentationPart.Presentation;
foreach (SlideId slideId in presentation.SlideIdList)
{
SlidePart slidePart = doc.PresentationPart.GetPartById(slideId.RelationshipId) as SlidePart;
if (slidePart == null || slidePart.Slide == null)
{
continue;
}
Slide slide = slidePart.Slide;
var videos = slide.Descendants<Video>();
Console.Out.WriteLine("Found videos for slide ID: {0}", slideId.Id);
foreach (Video video in videos)
{
ShapeTarget shapeTarget = video.Descendants<ShapeTarget>().FirstOrDefault();
Console.Out.WriteLine("ShapeTargetId = {0}", shapeTarget.ShapeId);
var videoFromFile = slide.CommonSlideData.ShapeTree.Descendants<Picture>().
Where<Picture>(p => p.NonVisualPictureProperties.Descendants<NonVisualDrawingProperties>().FirstOrDefault().Id == shapeTarget.ShapeId).
FirstOrDefault().Descendants<VideoFromFile>().FirstOrDefault();
Console.Out.WriteLine("Releationship ID: {0}", videoFromFile.Link);
var externalReleationship =
slidePart.ExternalRelationships.Where(er => er.Id == videoFromFile.Link).FirstOrDefault();
if(externalReleationship == null) // Then it must be embedded
{
ReferenceRelationship rr = slidePart.GetReferenceRelationship(videoFromFile.Link);
if (rr != null)
{
Console.Out.WriteLine(rr.Uri.OriginalString);
}
}
else
{
Console.Out.WriteLine("Path to video file: {0}", externalReleationship.Uri.AbsolutePath);
}
}
}
}
当然,您也可以直接枚举a:videoFile(类VideoFromFile
)标签。请参见下面的代码。
foreach (SlideId slideId in presentation.SlideIdList)
{
SlidePart slidePart = doc.PresentationPart.GetPartById(slideId.RelationshipId) as SlidePart;
if (slidePart == null || slidePart.Slide == null)
{
continue;
}
Slide slide = slidePart.Slide;
var videos = slide.CommonSlideData.ShapeTree.Descendants<VideoFromFile>();
foreach (VideoFromFile video in videos)
{
Console.Out.WriteLine("Releationship ID: {0}", video.Link);
var externalReleationship =
slidePart.ExternalRelationships.Where(er => er.Id == video.Link).FirstOrDefault();
if(externalReleationship == null)
{
ReferenceRelationship rr = slidePart.GetReferenceRelationship(videoFromFile.Link);
if (rr != null)
{
Console.Out.WriteLine(rr.Uri.OriginalString);
}
}
else
{
Console.Out.WriteLine("Path to video file: {0}", externalReleationship.Uri.AbsolutePath);
}
}
}
请原谅我重新提出这个长期存在的问题,但是我遇到了完全相同的问题,并且我有一个解决方案,无需挖掘幻灯片XML即可找到元素。事实证明,视频和媒体部分没有出现在slidePart.Parts
集合中(如OP所述),但它们do出现在了另一个集合slidePart.DataPartReferenceRelationships
中。因此,我能够找到对嵌入式视频的引用,如下所示:
SlidePart slidePart = ...;
foreach(var videoPart in slidePart.DataPartReferenceRelationships.OfType<VideoReferenceRelationship>())
Console.WriteLine("Video Part ID: " + videoPart.Id);
可能对OP有用一点,但希望它可以节省一些时间:)