在OpenXML中找到视频关系

时间:2012-09-19 22:53:06

标签: video openxml

所以我正在编写一个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?

2 个答案:

答案 0 :(得分:3)

视频关联存储在SlidePart的ExternalReleationships集合中。

Powerpoint以下列方式(简化)将视频(外部文件)嵌入到演示文稿中:

  1. 在p:timing(class Video)标记内创建p:video(class Timing)标记  包含视频的幻灯片。
  2. p:video标签包含一个名为p:cMediaNode(class CommonMediaNode)的子项。

  3. p:cMediaNode包含一个名为p:tgtEl(class TargetElement)的子项。

  4. 同样,p:cMediaNode包含一个名为p:spTgt(class ShapeTarget)的子项, 指向与视频相关的图片形状的ID。图片的ID 形状存储在NonVisualDrawingProperties Id成员中。 因此,视频通过这些ID连接到图像形状。

  5. 此外,图片形状包含一个名为a:videoFile(class VideoFromFile)的子项。 VideoFromFile类有一个名为Link的成员,它指向Id的ID 外部关系。

  6. 我强烈建议您下载 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(class 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);
        }
      }
    }
    

答案 1 :(得分:0)

请原谅我复活这个久违的问题,但是我遇到了完全相同的问题,并且我有一个解决方案,不需要挖掘幻灯片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有用可能有点晚了,但希望它可以节省一些时间:)