private static void BuildDocument(List<Source> sources, WordprocessingDocument output) { if (RelationshipMarkup == null) RelationshipMarkup = new Dictionary<XName, XName[]>() { //{ button, new [] { image }}, { A.blip, new [] { R.embed, R.link }}, { A.hlinkClick, new [] { R.id }}, { A.relIds, new [] { R.cs, R.dm, R.lo, R.qs }}, //{ a14:imgLayer, new [] { R.embed }}, //{ ax:ocx, new [] { R.id }}, { C.chart, new [] { R.id }}, { C.externalData, new [] { R.id }}, { C.userShapes, new [] { R.id }}, { DGM.relIds, new [] { R.cs, R.dm, R.lo, R.qs }}, { O.OLEObject, new [] { R.id }}, { VML.fill, new [] { R.id }}, { VML.imagedata, new [] { R.href, R.id, R.pict }}, { VML.stroke, new [] { R.id }}, { W.altChunk, new [] { R.id }}, { W.attachedTemplate, new [] { R.id }}, { W.control, new [] { R.id }}, { W.dataSource, new [] { R.id }}, { W.embedBold, new [] { R.id }}, { W.embedBoldItalic, new [] { R.id }}, { W.embedItalic, new [] { R.id }}, { W.embedRegular, new [] { R.id }}, { W.footerReference, new [] { R.id }}, { W.headerReference, new [] { R.id }}, { W.headerSource, new [] { R.id }}, { W.hyperlink, new [] { R.id }}, { W.printerSettings, new [] { R.id }}, { W.recipientData, new [] { R.id }}, // Mail merge, not required { W.saveThroughXslt, new [] { R.id }}, { W.sourceFileName, new [] { R.id }}, // Framesets, not required { W.src, new [] { R.id }}, // Mail merge, not required { W.subDoc, new [] { R.id }}, // Sub documents, not required //{ w14:contentPart, new [] { R.id }}, { WNE.toolbarData, new [] { R.id }}, }; // This list is used to eliminate duplicate images List<ImageData> images = new List<ImageData>(); XDocument mainPart = output.MainDocumentPart.GetXDocument(); mainPart.Declaration.Standalone = "yes"; mainPart.Declaration.Encoding = "UTF-8"; mainPart.Root.ReplaceWith( new XElement(W.document, NamespaceAttributes, new XElement(W.body))); if (sources.Count > 0) { using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(sources[0].WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { CopyStartingParts(doc, output, images); } int sourceNum = 0; foreach (Source source in sources) { if (source.InsertId != null) { while (true) { XDocument mainXDoc = output.MainDocumentPart.GetXDocument(); if (!mainXDoc.Descendants(PtOpenXml.Insert).Any(d => (string)d.Attribute(PtOpenXml.Id) == source.InsertId)) break; using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(source.WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { #if TestForUnsupportedDocuments // throws exceptions if a document contains unsupported content TestForUnsupportedDocument(doc, sources.IndexOf(source)); #endif List<XElement> contents = doc.MainDocumentPart.GetXDocument() .Root .Element(W.body) .Elements() .Skip(source.Start) .Take(source.Count) .ToList(); try { AppendDocument(doc, output, contents, source.KeepSections, source.InsertId, images); } catch (DocumentBuilderInternalException dbie) { if (dbie.Message.Contains("{0}")) throw new DocumentBuilderException(string.Format(dbie.Message, sourceNum)); else throw dbie; } } } } else { using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(source.WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { #if TestForUnsupportedDocuments // throws exceptions if a document contains unsupported content TestForUnsupportedDocument(doc, sources.IndexOf(source)); #endif List<XElement> contents = doc.MainDocumentPart.GetXDocument() .Root .Element(W.body) .Elements() .Skip(source.Start) .Take(source.Count) .ToList(); try { AppendDocument(doc, output, contents, source.KeepSections, null, images); } catch (DocumentBuilderInternalException dbie) { if (dbie.Message.Contains("{0}")) throw new DocumentBuilderException(string.Format(dbie.Message, sourceNum)); else throw dbie; } } } ++sourceNum; } if (!sources.Any(s => s.KeepSections)) { using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(sources[0].WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { var sectPr = doc.MainDocumentPart.GetXDocument().Root.Element(W.body) .Elements().Last(); if (sectPr.Name == W.sectPr) { AddSectionAndDependencies(doc, output, sectPr, images); output.MainDocumentPart.GetXDocument().Root.Element(W.body).Add(sectPr); } } } else FixUpSectionProperties(output); } foreach (var part in output.GetAllParts()) if (part.Annotation<XDocument>() != null) part.PutXDocument(); }
private static void BuildDocument(List<Source> sources, WordprocessingDocument output) { if (RelationshipMarkup == null) RelationshipMarkup = new Dictionary<XName, XName[]>() { //{ button, new [] { image }}, { A.blip, new [] { R.embed, R.link }}, { A.hlinkClick, new [] { R.id }}, { A.relIds, new [] { R.cs, R.dm, R.lo, R.qs }}, //{ a14:imgLayer, new [] { R.embed }}, //{ ax:ocx, new [] { R.id }}, { C.chart, new [] { R.id }}, { C.externalData, new [] { R.id }}, { C.userShapes, new [] { R.id }}, { DGM.relIds, new [] { R.cs, R.dm, R.lo, R.qs }}, { O.OLEObject, new [] { R.id }}, { VML.fill, new [] { R.id }}, { VML.imagedata, new [] { R.href, R.id, R.pict }}, { VML.stroke, new [] { R.id }}, { W.altChunk, new [] { R.id }}, { W.attachedTemplate, new [] { R.id }}, { W.control, new [] { R.id }}, { W.dataSource, new [] { R.id }}, { W.embedBold, new [] { R.id }}, { W.embedBoldItalic, new [] { R.id }}, { W.embedItalic, new [] { R.id }}, { W.embedRegular, new [] { R.id }}, { W.footerReference, new [] { R.id }}, { W.headerReference, new [] { R.id }}, { W.headerSource, new [] { R.id }}, { W.hyperlink, new [] { R.id }}, { W.printerSettings, new [] { R.id }}, { W.recipientData, new [] { R.id }}, // Mail merge, not required { W.saveThroughXslt, new [] { R.id }}, { W.sourceFileName, new [] { R.id }}, // Framesets, not required { W.src, new [] { R.id }}, // Mail merge, not required { W.subDoc, new [] { R.id }}, // Sub documents, not required //{ w14:contentPart, new [] { R.id }}, { WNE.toolbarData, new [] { R.id }}, }; // This list is used to eliminate duplicate images List<ImageData> images = new List<ImageData>(); XDocument mainPart = output.MainDocumentPart.GetXDocument(); mainPart.Declaration.Standalone = "yes"; mainPart.Declaration.Encoding = "UTF-8"; mainPart.Root.ReplaceWith( new XElement(W.document, NamespaceAttributes, new XElement(W.body))); if (sources.Count > 0) { using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(sources[0].WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { CopyStartingParts(doc, output, images); } int sourceNum = 0; foreach (Source source in sources) { if (source.InsertId != null) { while (true) { XDocument mainXDoc = output.MainDocumentPart.GetXDocument(); if (!mainXDoc.Descendants(PtOpenXml.Insert).Any(d => (string)d.Attribute(PtOpenXml.Id) == source.InsertId)) break; using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(source.WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { #if TestForUnsupportedDocuments // throws exceptions if a document contains unsupported content TestForUnsupportedDocument(doc, sources.IndexOf(source)); #endif if (source.KeepSections && source.DiscardHeadersAndFootersInKeptSections) RemoveHeadersAndFootersFromSections(doc); else if (source.KeepSections) ProcessSectionsForLinkToPreviousHeadersAndFooters(doc); List<XElement> contents = doc.MainDocumentPart.GetXDocument() .Root .Element(W.body) .Elements() .Skip(source.Start) .Take(source.Count) .ToList(); try { AppendDocument(doc, output, contents, source.KeepSections, source.InsertId, images); } catch (DocumentBuilderInternalException dbie) { if (dbie.Message.Contains("{0}")) throw new DocumentBuilderException(string.Format(dbie.Message, sourceNum)); else throw dbie; } } } } else { using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(source.WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { #if TestForUnsupportedDocuments // throws exceptions if a document contains unsupported content TestForUnsupportedDocument(doc, sources.IndexOf(source)); #endif if (source.KeepSections && source.DiscardHeadersAndFootersInKeptSections) RemoveHeadersAndFootersFromSections(doc); else if (source.KeepSections) ProcessSectionsForLinkToPreviousHeadersAndFooters(doc); List<XElement> contents = doc.MainDocumentPart.GetXDocument() .Root .Element(W.body) .Elements() .Skip(source.Start) .Take(source.Count) .ToList(); try { AppendDocument(doc, output, contents, source.KeepSections, null, images); } catch (DocumentBuilderInternalException dbie) { if (dbie.Message.Contains("{0}")) throw new DocumentBuilderException(string.Format(dbie.Message, sourceNum)); else throw dbie; } } } ++sourceNum; } if (!sources.Any(s => s.KeepSections)) { using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(sources[0].WmlDocument)) using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) { var sectPr = doc.MainDocumentPart.GetXDocument().Root.Element(W.body) .Elements().Last(); if (sectPr.Name == W.sectPr) { AddSectionAndDependencies(doc, output, sectPr, images); output.MainDocumentPart.GetXDocument().Root.Element(W.body).Add(sectPr); } } } else { FixUpSectionProperties(output); // Any sectPr elements that do not have headers and footers should take their headers and footers from the *next* section, // i.e. from the running section. var mxd = output.MainDocumentPart.GetXDocument(); var sections = mxd.Descendants(W.sectPr).Reverse().ToList(); CachedHeaderFooter[] cachedHeaderFooter = new[] { new CachedHeaderFooter() { Ref = W.headerReference, Type = "first" }, new CachedHeaderFooter() { Ref = W.headerReference, Type = "even" }, new CachedHeaderFooter() { Ref = W.headerReference, Type = "default" }, new CachedHeaderFooter() { Ref = W.footerReference, Type = "first" }, new CachedHeaderFooter() { Ref = W.footerReference, Type = "even" }, new CachedHeaderFooter() { Ref = W.footerReference, Type = "default" }, }; bool firstSection = true; foreach (var sect in sections) { if (firstSection) { foreach (var hf in cachedHeaderFooter) { var referenceElement = sect.Elements(hf.Ref).FirstOrDefault(z => (string)z.Attribute(W.type) == hf.Type); if (referenceElement != null) hf.CachedPartRid = (string)referenceElement.Attribute(R.id); } firstSection = false; continue; } else { CopyOrCacheHeaderOrFooter(output, cachedHeaderFooter, sect, W.headerReference, "first"); CopyOrCacheHeaderOrFooter(output, cachedHeaderFooter, sect, W.headerReference, "even"); CopyOrCacheHeaderOrFooter(output, cachedHeaderFooter, sect, W.headerReference, "default"); CopyOrCacheHeaderOrFooter(output, cachedHeaderFooter, sect, W.footerReference, "first"); CopyOrCacheHeaderOrFooter(output, cachedHeaderFooter, sect, W.footerReference, "even"); CopyOrCacheHeaderOrFooter(output, cachedHeaderFooter, sect, W.footerReference, "default"); } } } } foreach (var part in output.GetAllParts()) if (part.Annotation<XDocument>() != null) part.PutXDocument(); }
private static bool ValidateWordprocessingDocument(WordprocessingDocument wDoc, List<XElement> metrics, List<string> notes, Dictionary<XName, int> metricCountDictionary) { bool valid = ValidateAgainstSpecificVersion(wDoc, metrics, DocumentFormat.OpenXml.FileFormatVersions.Office2007, H.SdkValidationError2007); valid |= ValidateAgainstSpecificVersion(wDoc, metrics, DocumentFormat.OpenXml.FileFormatVersions.Office2010, H.SdkValidationError2010); #if !NET35 valid |= ValidateAgainstSpecificVersion(wDoc, metrics, DocumentFormat.OpenXml.FileFormatVersions.Office2013, H.SdkValidationError2013); #endif int elementCount = 0; int paragraphCount = 0; int textCount = 0; foreach (var part in wDoc.ContentParts()) { XDocument xDoc = part.GetXDocument(); foreach (var e in xDoc.Descendants()) { if (e.Name == W.txbxContent) IncrementMetric(metricCountDictionary, H.TextBox); else if (e.Name == W.sdt) IncrementMetric(metricCountDictionary, H.ContentControl); else if (e.Name == W.customXml) IncrementMetric(metricCountDictionary, H.CustomXmlMarkup); else if (e.Name == W.fldChar) IncrementMetric(metricCountDictionary, H.ComplexField); else if (e.Name == W.fldSimple) IncrementMetric(metricCountDictionary, H.SimpleField); else if (e.Name == W.altChunk) IncrementMetric(metricCountDictionary, H.AltChunk); else if (e.Name == W.tbl) IncrementMetric(metricCountDictionary, H.Table); else if (e.Name == W.hyperlink) IncrementMetric(metricCountDictionary, H.Hyperlink); else if (e.Name == W.framePr) IncrementMetric(metricCountDictionary, H.LegacyFrame); else if (e.Name == W.control) IncrementMetric(metricCountDictionary, H.ActiveX); else if (e.Name == W.subDoc) IncrementMetric(metricCountDictionary, H.SubDocument); else if (e.Name == VML.imagedata || e.Name == VML.fill || e.Name == VML.stroke || e.Name == A.blip) { var relId = (string)e.Attribute(R.embed); if (relId != null) ValidateImageExists(part, relId, metricCountDictionary); relId = (string)e.Attribute(R.pict); if (relId != null) ValidateImageExists(part, relId, metricCountDictionary); relId = (string)e.Attribute(R.id); if (relId != null) ValidateImageExists(part, relId, metricCountDictionary); } if (part.Uri == wDoc.MainDocumentPart.Uri) { elementCount++; if (e.Name == W.p) paragraphCount++; if (e.Name == W.t) textCount += ((string)e).Length; } } } foreach (var item in metricCountDictionary) { metrics.Add( new XElement(item.Key, new XAttribute(H.Val, item.Value))); } metrics.Add(new XElement(H.ElementCount, new XAttribute(H.Val, elementCount))); metrics.Add(new XElement(H.AverageParagraphLength, new XAttribute(H.Val, (int)((double)textCount / (double)paragraphCount)))); if (RevisionAccepter.HasTrackedRevisions(wDoc)) metrics.Add(new XElement(H.RevisionTracking, new XAttribute(H.Val, true))); if (wDoc.GetAllParts().Any(part => part.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) metrics.Add(new XElement(H.EmbeddedXlsx, new XAttribute(H.Val, true))); NumberingFormatListAssembly(wDoc, metrics); XDocument wxDoc = wDoc.MainDocumentPart.GetXDocument(); foreach (var d in wxDoc.Descendants()) { if (d.Name == W.saveThroughXslt) { string rid = (string)d.Attribute(R.id); var tempExternalRelationship = wDoc .MainDocumentPart .DocumentSettingsPart .ExternalRelationships .FirstOrDefault(h => h.Id == rid); if (tempExternalRelationship == null) metrics.Add(new XElement(H.InvalidSaveThroughXslt, new XAttribute(H.Val, true))); valid = false; } else if (d.Name == W.trackRevisions) metrics.Add(new XElement(H.TrackRevisionsEnabled, new XAttribute(H.Val, true))); else if (d.Name == W.documentProtection) metrics.Add(new XElement(H.DocumentProtection, new XAttribute(H.Val, true))); } FontAndCharSetAnalysis(wDoc, metrics, notes); return valid; }
private static XElement GetMetricsForWmlPart(WordprocessingDocument noTrackedDocument, OpenXmlPart part, MetricsGetterSettings settings) { XElement contentControls = null; if (part is MainDocumentPart || part is HeaderPart || part is FooterPart || part is FootnotesPart || part is EndnotesPart) { var noTrackedPart = noTrackedDocument.GetAllParts().FirstOrDefault(p => p.Uri == part.Uri); if (noTrackedPart == null) throw new OpenXmlPowerToolsException("Internal error"); var xd = noTrackedPart.GetXDocument(); contentControls = (XElement)GetContentControlsTransform(xd.Root, settings); if (!contentControls.HasElements) contentControls = null; } var partMetrics = new XElement(H.Part, new XAttribute(H.ContentType, part.ContentType), new XAttribute(H.Uri, part.Uri.ToString()), contentControls); if (partMetrics.HasElements) return partMetrics; return null; }
private static XElement GetWmlMetrics(string fileName, bool invalidHyperlink, WordprocessingDocument document, WordprocessingDocument noTrackedDocument, MetricsGetterSettings settings) { var parts = new XElement(H.Parts, document.GetAllParts().Select(part => { return GetMetricsForWmlPart(noTrackedDocument, part, settings); })); if (!parts.HasElements) parts = null; var metrics = new XElement(H.Metrics, new XAttribute(H.FileName, fileName), new XAttribute(H.FileType, "WordprocessingML"), GetStyleHierarchy(document), GetMiscWmlMetrics(document, noTrackedDocument, invalidHyperlink), parts); return metrics; }