Powerpoint Best Practices Implementation
Implementation Notes
Slide Layout
For each slide (N):
- find the linked slide layout by looking in ppt\slides\_rels\slideN.xml.rels
- open the slide layout xml in ppt\slideLayout
- check the name attribute for <cSld> - if it's blank then give an error
or search for a <p:ph> tag in the xml - if you don't find any then it may be a blank layout
Slide Titles
Existence of Titles
void Check_Title_Existence(XmlDocument xmlDoc, XmlNamespaceManager xmlnsManager) { XmlNodeList TitleList = xmlDoc.SelectNodes("//p:sp//p:ph[@type='title'] | //p:sp//p:ph[@type='ctrTitle']", xmlnsManager); int num_title_boxes = 0; foreach (XmlNode listItem in TitleList) { num_title_boxes++; } MessageBox.Show("Number of Title Boxes: " + num_title_boxes.ToString()); }
Empty Titles
void Check_Title_Empty(XmlDocument xmlDoc, XmlNamespaceManager xmlnsManager) { XmlNodeList TitleList = xmlDoc.SelectNodes("//p:ph[@type='title'] | //p:ph[@type='ctrTitle']", xmlnsManager); int num_empty_title_boxes = 0; if (TitleList != null) { for (int i = 0; i < TitleList.Count; i++) { if (TitleList[i] != null) { XmlNode Grandparent = TitleList[i].SelectSingleNode("ancestor::p:sp", xmlnsManager); if (Grandparent != null) { XmlNode TitleText = Grandparent.SelectSingleNode(".//a:t", xmlnsManager); if (TitleText == null) { num_empty_title_boxes++; } else if (TitleText.InnerText.Equals("")) { num_empty_title_boxes++; } } } } } MessageBox.Show("Number of Empty Title Boxes: " + num_empty_title_boxes.ToString()); }
Alternative text for images
Picture, Clipart, and Media
Note: Media doesn't necessarily work yet, since they have different extensions than picture files.
private void checkPicTags(XmlDocument xmlDoc, XmlNamespaceManager xmlnsManager, int i) { /* All SmartArt images can be found within a <p:graphicFrame> tag. * In addition, their alternative text will be described in a descr attribute. The complete structure to this would be: * ...<p:graphicFrame> * <p:nvGraphicFramePr> * <p:cNvPr descr="smartart" /> * </p:nvGraphicFramePr> * </p:graphicFrame> */ XmlNodeList smartartList = xmlDoc.SelectNodes("//p:graphicFrame", xmlnsManager); foreach (XmlNode smartart in smartartList) { XmlNode graphicFramePr = smartart.SelectSingleNode("./p:nvGraphicFramePr", xmlnsManager); if (graphicFramePr == null) // we can't find a nvPicPr tag { MessageBox.Show("Couldn't find p:nvGraphicFramePr tag in " + i); continue; } XmlNode nvPr = graphicFramePr.SelectSingleNode("./p:cNvPr", xmlnsManager); if (nvPr == null) { MessageBox.Show("Couldn't find p:cNvPr tag in " + i); } XmlNode descrTag = nvPr.Attributes.GetNamedItem("descr"); if (descrTag == null) { MessageBox.Show("No alternative text for smartart! in " + i); } else if (descrTag.Value.Equals("")) { MessageBox.Show("No alternative text for smartart! in " + i); } }
SmartArt
private void checkPicTags(XmlDocument xmlDoc, XmlNamespaceManager xmlnsManager, int i) { /* Begin by checking for clipart, inserted images, and media clips. These are all contained within a <p:pic> tag. * In addition, their alternative text will be described in a descr attribute. The complete structure to this would be: * ...<p:pic> * <p:nvPicPr> * <p:cNvPr descr="image.jpg" /> * </p:nvPicPr> * </p:pic> */ XmlNodeList picList = xmlDoc.SelectNodes("//p:pic", xmlnsManager); foreach (XmlNode pic in picList) { XmlNode picPr = pic.SelectSingleNode("./p:nvPicPr", xmlnsManager); if (picPr == null) // we can't find a nvPicPr tag { MessageBox.Show("Couldn't find p:nvPicPr tag in " + i); continue; } XmlNode nvPr = picPr.SelectSingleNode("./p:cNvPr", xmlnsManager); if (nvPr == null) { MessageBox.Show("Couldn't find p:cNvPr tag in " + i); } XmlNode descrTag = nvPr.Attributes.GetNamedItem("descr"); if (descrTag == null) { MessageBox.Show("No alternative text for image! in " + i); } else if (descrTag.Value.Equals("") || Regex.IsMatch(descrTag.Value, untaggedImagePattern)) { MessageBox.Show("No alternative text for image! in " + i); } } }