private static void ProcessTemplatePart(XElement data, TemplateError te, OpenXmlPart part)
        {
            XDocument xDoc = part.GetXDocument();

            var xDocRoot = RemoveGoBackBookmarks(xDoc.Root);

            // content controls in cells can surround the W.tc element, so transform so that such content controls are within the cell content
            xDocRoot = (XElement)NormalizeContentControlsInCells(xDocRoot);

            xDocRoot = (XElement)TransformToMetadata(xDocRoot, data, te);

            // Table might have been placed at run-level, when it should be at block-level, so fix this.
            // Repeat, EndRepeat, Conditional, EndConditional are allowed at run level, but only if there is a matching pair
            // if there is only one Repeat, EndRepeat, Conditional, EndConditional, then move to block level.
            // if there is a matching pair, then is OK.
            xDocRoot = (XElement)ForceBlockLevelAsAppropriate(xDocRoot, te);

            NormalizeTablesRepeatAndConditional(xDocRoot, te);

            // any EndRepeat, EndConditional that remain are orphans, so replace with an error
            ProcessOrphanEndRepeatEndConditional(xDocRoot, te);

            // do the actual content replacement
            xDocRoot = (XElement)ContentReplacementTransform(xDocRoot, data, te);

            xDoc.Elements().First().ReplaceWith(xDocRoot);
            part.PutXDocument();
            return;
        }
示例#2
0
        private static void WriteError(TemplateError error)
        {
            ConsoleColor color = Console.ForegroundColor;

            Console.ForegroundColor = error.Warning ? ConsoleColor.Yellow : ConsoleColor.Red;

            Console.Error.Write(FormatError(error));

            Console.ForegroundColor = color;
        }
        private static XElement CreateRunErrorMessage(string errorMessage, TemplateError templateError)
        {
            templateError.HasError = true;
            var errorRun = new XElement(W.r,
                                        new XElement(W.rPr,
                                                     new XElement(W.color, new XAttribute(W.val, "FF0000")),
                                                     new XElement(W.highlight, new XAttribute(W.val, "yellow"))),
                                        new XElement(W.t, errorMessage));

            return(errorRun);
        }
        private static object ForceBlockLevelAsAppropriate(XNode node, TemplateError te)
        {
            XElement element = node as XElement;

            if (element != null)
            {
                if (element.Name == W.p)
                {
                    var childMeta = element.Elements().Where(n => s_MetaToForceToBlock.Contains(n.Name)).ToList();
                    if (childMeta.Count() == 1)
                    {
                        var child = childMeta.First();
                        var otherTextInParagraph = element.Elements(W.r).Elements(W.t).Select(t => (string)t).StringConcatenate().Trim();
                        if (otherTextInParagraph != "")
                        {
                            var newPara = new XElement(element);
                            var newMeta = newPara.Elements().Where(n => s_MetaToForceToBlock.Contains(n.Name)).First();
                            newMeta.ReplaceWith(CreateRunErrorMessage("Error: Unmatched metadata can't be in paragraph with other text", te));
                            return(newPara);
                        }
                        var meta = new XElement(child.Name,
                                                child.Attributes(),
                                                new XElement(W.p,
                                                             element.Attributes(),
                                                             element.Elements(W.pPr),
                                                             child.Elements()));
                        return(meta);
                    }
                    var count = childMeta.Count();
                    if (count % 2 == 0)
                    {
                        if (childMeta.Where(c => c.Name == PA.Repeat).Count() != childMeta.Where(c => c.Name == PA.EndRepeat).Count())
                        {
                            return(CreateContextErrorMessage(element, "Error: Mismatch Repeat / EndRepeat at run level", te));
                        }
                        if (childMeta.Where(c => c.Name == PA.Conditional).Count() != childMeta.Where(c => c.Name == PA.EndConditional).Count())
                        {
                            return(CreateContextErrorMessage(element, "Error: Mismatch Conditional / EndConditional at run level", te));
                        }
                        return(new XElement(element.Name,
                                            element.Attributes(),
                                            element.Nodes().Select(n => ForceBlockLevelAsAppropriate(n, te))));
                    }
                    else
                    {
                        return(CreateContextErrorMessage(element, "Error: Invalid metadata at run level", te));
                    }
                }
                return(new XElement(element.Name,
                                    element.Attributes(),
                                    element.Nodes().Select(n => ForceBlockLevelAsAppropriate(n, te))));
            }
            return(node);
        }
 private static void ProcessOrphanEndRepeatEndConditional(XElement xDocRoot, TemplateError te)
 {
     foreach (var element in xDocRoot.Descendants(PA.EndRepeat).ToList())
     {
         var error = CreateContextErrorMessage(element, "Error: EndRepeat without matching Repeat", te);
         element.ReplaceWith(error);
     }
     foreach (var element in xDocRoot.Descendants(PA.EndConditional).ToList())
     {
         var error = CreateContextErrorMessage(element, "Error: EndConditional without matching Conditional", te);
         element.ReplaceWith(error);
     }
 }
示例#6
0
        internal void AddError(ref TemplateOutput templateOutput, Exception ex, Enums.LogLevel logLevel)
        {
            while (ex != null)
            {
                TemplateError te = new TemplateError()
                {
                    ErrorLevel       = logLevel,
                    Message          = ex.Message,
                    StackTrace       = ex.StackTrace,
                    TemplateIdentity = ProcessModel.TemplateIdentity.Copy()
                };

                templateOutput.Errors.Add(te);
                ex = ex.InnerException;
            }
        }
示例#7
0
        private static void ProcessTemplatePart(XElement data, TemplateError te, OpenXmlPart part)
        {
            XDocument xDoc = part.GetXDocument();

            XElement newRootElementWithMetadata = (XElement)TransformToMetadata(xDoc.Root, data, te);

            NormalizeTablesRepeatAndConditional(newRootElementWithMetadata, te);
            XElement newRootElement = newRootElementWithMetadata;

            // do the actual content replacement
            newRootElement = (XElement)ContentReplacementTransform(newRootElement, data, te);

            xDoc.Elements().First().ReplaceWith(newRootElement);
            part.PutXDocument();
            return;
        }
        private static void ProcessTemplatePart(XElement data, TemplateError te, OpenXmlPart part)
        {
            XDocument xDoc = part.GetXDocument();

            XElement newRootElementWithMetadata = (XElement)TransformToMetadata(xDoc.Root, data, te);

            NormalizeTablesRepeatAndConditional(newRootElementWithMetadata, te);
            XElement newRootElement = newRootElementWithMetadata;

            // do the actual content replacement
            newRootElement = (XElement)ContentReplacementTransform(newRootElement, data, te);

            xDoc.Elements().First().ReplaceWith(newRootElement);
            part.PutXDocument();
            return;
        }
示例#9
0
        private static XElement TransformXmlTextToMetadata(TemplateError te, string xmlText)
        {
            XElement xml;

            try
            {
                xml = XElement.Parse(xmlText);
            }
            catch (XmlException e)
            {
                return(CreateParaErrorMessage("XmlException: " + e.Message, te));
            }
            //string schemaError = ValidatePerSchema(xml);
            //if (schemaError != null)
            //    return CreateParaErrorMessage("Schema Validation Error: " + schemaError, te);
            return(xml);
        }
示例#10
0
        public static CachedTemplate Parse(string input, bool bypass = false)
        {
            Guard.NotNull(input);

            CachedTemplate result;

            if (!bypass)
            {
                LockObject.EnterWriteLock();
                try
                {
                    if (Cache.TryGetValue(input, out result))
                    {
                        return(result);
                    }
                }
                finally
                {
                    LockObject.ExitWriteLock();
                }
            }

            Parser.TryParse(input, out var template, out var errorMessage);

            var error = TemplateError.Parse(errorMessage);

            result = new CachedTemplate(template, error);

            if (!bypass)
            {
                LockObject.EnterWriteLock();
                try
                {
                    Cache.Set(input, result);
                }
                finally
                {
                    LockObject.ExitWriteLock();
                }
            }

            return(result);
        }
        public static WmlDocument AssembleDocument(WmlDocument templateDoc, XElement data, out bool templateError)
        {
            byte[] byteArray = templateDoc.DocumentByteArray;
            using (MemoryStream mem = new MemoryStream())
            {
                mem.Write(byteArray, 0, (int)byteArray.Length);
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
                {
                    if (RevisionAccepter.HasTrackedRevisions(wordDoc))
                        throw new OpenXmlPowerToolsException("Invalid DocumentAssembler template - contains tracked revisions");

                    var te = new TemplateError();
                    foreach (var part in wordDoc.ContentParts())
                    {
                        ProcessTemplatePart(data, te, part);
                    }
                    templateError = te.HasError;
                }
                WmlDocument assembledDocument = new WmlDocument("TempFileName.docx", mem.ToArray());
                return assembledDocument;
            }
        }
        public static WmlDocument AssembleDocument(WmlDocument templateDoc, XElement data, out bool templateError)
        {
            byte[] byteArray = templateDoc.DocumentByteArray;
            using (MemoryStream mem = new MemoryStream())
            {
                mem.Write(byteArray, 0, (int)byteArray.Length);
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
                {
                    if (RevisionAccepter.HasTrackedRevisions(wordDoc))
                    {
                        throw new OpenXmlPowerToolsException("Invalid DocumentAssembler template - contains tracked revisions");
                    }

                    var te = new TemplateError();
                    foreach (var part in wordDoc.ContentParts())
                    {
                        ProcessTemplatePart(data, te, part);
                    }
                    templateError = te.HasError;
                }
                WmlDocument assembledDocument = new WmlDocument("TempFileName.docx", mem.ToArray());
                return(assembledDocument);
            }
        }
示例#13
0
 private void GenerateError(TemplateError error)
 {
     GenerateError(error.Warning, error.Message, error.Line, error.Column);
 }
        private static object TransformToMetadata(XNode node, XElement data, TemplateError te)
        {
            XElement element = node as XElement;

            if (element != null)
            {
                if (element.Name == W.sdt)
                {
                    var alias = (string)element.Elements(W.sdtPr).Elements(W.alias).Attributes(W.val).FirstOrDefault();
                    if (alias == null || alias == "" || s_AliasList.Contains(alias))
                    {
                        var ccContents = element
                                         .DescendantsTrimmed(W.txbxContent)
                                         .Where(e => e.Name == W.t)
                                         .Select(t => (string)t)
                                         .StringConcatenate()
                                         .Trim()
                                         .Replace('“', '"')
                                         .Replace('”', '"');
                        if (ccContents.StartsWith("<"))
                        {
                            XElement xml = TransformXmlTextToMetadata(te, ccContents);
                            if (xml.Name == W.p || xml.Name == W.r)  // this means there was an error processing the XML.
                            {
                                if (element.Parent.Name == W.p)
                                {
                                    return(xml.Elements(W.r));
                                }
                                return(xml);
                            }
                            if (alias != null && xml.Name.LocalName != alias)
                            {
                                if (element.Parent.Name == W.p)
                                {
                                    return(CreateRunErrorMessage("Error: Content control alias does not match metadata element name", te));
                                }
                                else
                                {
                                    return(CreateParaErrorMessage("Error: Content control alias does not match metadata element name", te));
                                }
                            }
                            xml.Add(element.Elements(W.sdtContent).Elements());
                            return(xml);
                        }
                        return(new XElement(element.Name,
                                            element.Attributes(),
                                            element.Nodes().Select(n => TransformToMetadata(n, data, te))));
                    }
                    return(new XElement(element.Name,
                                        element.Attributes(),
                                        element.Nodes().Select(n => TransformToMetadata(n, data, te))));
                }
                if (element.Name == W.p)
                {
                    var paraContents = element
                                       .DescendantsTrimmed(W.txbxContent)
                                       .Where(e => e.Name == W.t)
                                       .Select(t => (string)t)
                                       .StringConcatenate()
                                       .Trim();
                    int occurances = paraContents.Select((c, i) => paraContents.Substring(i)).Count(sub => sub.StartsWith("<#"));
                    if (paraContents.StartsWith("<#") && paraContents.EndsWith("#>") && occurances == 1)
                    {
                        var      xmlText = paraContents.Substring(2, paraContents.Length - 4).Trim();
                        XElement xml     = TransformXmlTextToMetadata(te, xmlText);
                        if (xml.Name == W.p || xml.Name == W.r)
                        {
                            return(xml);
                        }
                        xml.Add(element);
                        return(xml);
                    }
                    if (paraContents.Contains("<#"))
                    {
                        List <RunReplacementInfo> runReplacementInfo = new List <RunReplacementInfo>();
                        var      thisGuid = Guid.NewGuid().ToString();
                        var      r        = new Regex("<#.*?#>");
                        XElement xml      = null;
                        OpenXmlRegex.Replace(new[] { element }, r, thisGuid, (para, match) =>
                        {
                            var matchString = match.Value.Trim();
                            var xmlText     = matchString.Substring(2, matchString.Length - 4).Trim().Replace('“', '"').Replace('”', '"');
                            try
                            {
                                xml = XElement.Parse(xmlText);
                            }
                            catch (XmlException e)
                            {
                                RunReplacementInfo rri = new RunReplacementInfo()
                                {
                                    Xml = null,
                                    XmlExceptionMessage     = "XmlException: " + e.Message,
                                    SchemaValidationMessage = null,
                                };
                                runReplacementInfo.Add(rri);
                                return(true);
                            }
                            string schemaError = ValidatePerSchema(xml);
                            if (schemaError != null)
                            {
                                RunReplacementInfo rri = new RunReplacementInfo()
                                {
                                    Xml = null,
                                    XmlExceptionMessage     = null,
                                    SchemaValidationMessage = "Schema Validation Error: " + schemaError,
                                };
                                runReplacementInfo.Add(rri);
                                return(true);
                            }
                            RunReplacementInfo rri2 = new RunReplacementInfo()
                            {
                                Xml = xml,
                                XmlExceptionMessage     = null,
                                SchemaValidationMessage = null,
                            };
                            runReplacementInfo.Add(rri2);
                            return(true);
                        }, false);

                        var newPara = new XElement(element);
                        foreach (var rri in runReplacementInfo)
                        {
                            var runToReplace = newPara.Descendants(W.r).FirstOrDefault(rn => rn.Value == thisGuid && rn.Parent.Name != PA.Content);
                            if (runToReplace == null)
                            {
                                throw new OpenXmlPowerToolsException("Internal error");
                            }
                            if (rri.XmlExceptionMessage != null)
                            {
                                runToReplace.ReplaceWith(CreateRunErrorMessage(rri.XmlExceptionMessage, te));
                            }
                            else if (rri.SchemaValidationMessage != null)
                            {
                                runToReplace.ReplaceWith(CreateRunErrorMessage(rri.SchemaValidationMessage, te));
                            }
                            else
                            {
                                var newXml = new XElement(rri.Xml);
                                newXml.Add(runToReplace);
                                runToReplace.ReplaceWith(newXml);
                            }
                        }
                        var coalescedParagraph = WordprocessingMLUtil.CoalesceAdjacentRunsWithIdenticalFormatting(newPara);
                        return(coalescedParagraph);
                    }
                }

                return(new XElement(element.Name,
                                    element.Attributes(),
                                    element.Nodes().Select(n => TransformToMetadata(n, data, te))));
            }
            return(node);
        }
        // The following method is written using tree modification, not RPFT, because it is easier to write in this fashion.
        // These types of operations are not as easy to write using RPFT.
        // Unless you are completely clear on the semantics of LINQ to XML DML, do not make modifications to this method.
        private static void NormalizeTablesRepeatAndConditional(XElement xDoc, TemplateError te)
        {
            var tables = xDoc.Descendants(PA.Table).ToList();

            foreach (var table in tables)
            {
                var followingElement = table.ElementsAfterSelf().Where(e => e.Name == W.tbl || e.Name == W.p).FirstOrDefault();
                if (followingElement == null || followingElement.Name != W.tbl)
                {
                    table.ReplaceWith(CreateParaErrorMessage("Table metadata is not immediately followed by a table", te));
                    continue;
                }
                // remove superflous paragraph from Table metadata
                table.RemoveNodes();
                // detach w:tbl from parent, and add to Table metadata
                followingElement.Remove();
                table.Add(followingElement);
            }

            int repeatDepth      = 0;
            int conditionalDepth = 0;

            foreach (var metadata in xDoc.Descendants().Where(d =>
                                                              d.Name == PA.Repeat ||
                                                              d.Name == PA.Conditional ||
                                                              d.Name == PA.EndRepeat ||
                                                              d.Name == PA.EndConditional))
            {
                if (metadata.Name == PA.Repeat)
                {
                    ++repeatDepth;
                    metadata.Add(new XAttribute(PA.Depth, repeatDepth));
                    continue;
                }
                if (metadata.Name == PA.EndRepeat)
                {
                    metadata.Add(new XAttribute(PA.Depth, repeatDepth));
                    --repeatDepth;
                    continue;
                }
                if (metadata.Name == PA.Conditional)
                {
                    ++conditionalDepth;
                    metadata.Add(new XAttribute(PA.Depth, conditionalDepth));
                    continue;
                }
                if (metadata.Name == PA.EndConditional)
                {
                    metadata.Add(new XAttribute(PA.Depth, conditionalDepth));
                    --conditionalDepth;
                    continue;
                }
            }

            while (true)
            {
                bool didReplace = false;
                foreach (var metadata in xDoc.Descendants().Where(d => (d.Name == PA.Repeat || d.Name == PA.Conditional) && d.Attribute(PA.Depth) != null).ToList())
                {
                    var   depth           = (int)metadata.Attribute(PA.Depth);
                    XName matchingEndName = null;
                    if (metadata.Name == PA.Repeat)
                    {
                        matchingEndName = PA.EndRepeat;
                    }
                    else if (metadata.Name == PA.Conditional)
                    {
                        matchingEndName = PA.EndConditional;
                    }
                    if (matchingEndName == null)
                    {
                        throw new OpenXmlPowerToolsException("Internal error");
                    }
                    var matchingEnd = metadata.ElementsAfterSelf(matchingEndName).FirstOrDefault(end => { return((int)end.Attribute(PA.Depth) == depth); });
                    if (matchingEnd == null)
                    {
                        metadata.ReplaceWith(CreateParaErrorMessage(string.Format("{0} does not have matching {1}", metadata.Name.LocalName, matchingEndName.LocalName), te));
                        continue;
                    }
                    metadata.RemoveNodes();
                    var contentBetween = metadata.ElementsAfterSelf().TakeWhile(after => after != matchingEnd).ToList();
                    foreach (var item in contentBetween)
                    {
                        item.Remove();
                    }
                    contentBetween = contentBetween.Where(n => n.Name != W.bookmarkStart && n.Name != W.bookmarkEnd).ToList();
                    metadata.Add(contentBetween);
                    metadata.Attributes(PA.Depth).Remove();
                    matchingEnd.Remove();
                    didReplace = true;
                    break;
                }
                if (!didReplace)
                {
                    break;
                }
            }
        }
        private static object?ContentReplacementTransform(XNode node, XElement data, TemplateError templateError)
        {
            if (node is XElement element)
            {
                if (element.Name == PA.Content)
                {
                    var para = element.Descendants(W.p).FirstOrDefault();
                    var run  = element.Descendants(W.r).FirstOrDefault();

                    var xPath          = (string)element.Attribute(PA.Select);
                    var optionalString = (string)element.Attribute(PA.Optional);
                    var optional       = (optionalString != null && optionalString.ToLower() == "true");

                    string newValue;
                    try
                    {
                        newValue = EvaluateXPathToString(data, xPath, optional);
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, "XPathException: " + e.Message, templateError));
                    }

                    if (para != null)
                    {
                        var p = new XElement(W.p, para.Elements(W.pPr));
                        foreach (var line in newValue.Split('\n'))
                        {
                            p.Add(new XElement(W.r,
                                               para.Elements(W.r).Elements(W.rPr).FirstOrDefault(),
                                               (p.Elements().Count() > 1) ? new XElement(W.br) : null,
                                               new XElement(W.t, line)));
                        }
                        return(p);
                    }
                    else
                    {
                        var list = new List <XElement>();
                        foreach (var line in newValue.Split('\n'))
                        {
                            list.Add(new XElement(W.r,
                                                  run.Elements().Where(e => e.Name != W.t),
                                                  (list.Count > 0) ? new XElement(W.br) : null,
                                                  new XElement(W.t, line)));
                        }
                        return(list);
                    }
                }
                if (element.Name == PA.Repeat)
                {
                    var selector       = (string)element.Attribute(PA.Select);
                    var optionalString = (string)element.Attribute(PA.Optional);
                    var optional       = (optionalString != null && optionalString.ToLower() == "true");

                    IEnumerable <XElement> repeatingData;
                    try
                    {
                        repeatingData = data.XPathSelectElements(selector);
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, "XPathException: " + e.Message, templateError));
                    }
                    if (!repeatingData.Any())
                    {
                        if (optional)
                        {
                            return(null);
                        }
                        return(CreateContextErrorMessage(element, "Repeat: Select returned no data", templateError));
                    }
                    var newContent = repeatingData.Select(d =>
                    {
                        var content = element
                                      .Elements()
                                      .Select(e => ContentReplacementTransform(e, d, templateError))
                                      .ToList();
                        return(content);
                    })
                                     .ToList();
                    return(newContent);
                }
                if (element.Name == PA.Table)
                {
                    IEnumerable <XElement> tableData;
                    try
                    {
                        tableData = data.XPathSelectElements((string)element.Attribute(PA.Select));
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, "XPathException: " + e.Message, templateError));
                    }
                    if (!tableData.Any())
                    {
                        return(CreateContextErrorMessage(element, "Table Select returned no data", templateError));
                    }

                    var table    = element.Element(W.tbl);
                    var protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault();
                    var footerRowsBeforeTransform = table
                                                    .Elements(W.tr)
                                                    .Skip(2)
                                                    .ToList();
                    var footerRows = footerRowsBeforeTransform
                                     .Select(x => ContentReplacementTransform(x, data, templateError))
                                     .ToList();
                    if (protoRow == null)
                    {
                        return(CreateContextErrorMessage(element, string.Format("Table does not contain a prototype row"), templateError));
                    }

                    protoRow.Descendants(W.bookmarkStart).Remove();
                    protoRow.Descendants(W.bookmarkEnd).Remove();
                    var newTable = new XElement(W.tbl,
                                                table.Elements().Where(e => e.Name != W.tr),
                                                table.Elements(W.tr).FirstOrDefault(),
                                                tableData.Select(d =>
                                                                 new XElement(W.tr,
                                                                              protoRow.Elements().Where(r => r.Name != W.tc),
                                                                              protoRow.Elements(W.tc)
                                                                              .Select(tc =>
                    {
                        var paragraph   = tc.Elements(W.p).FirstOrDefault();
                        var cellRun     = paragraph.Elements(W.r).FirstOrDefault();
                        var xPath       = paragraph.Value;
                        string?newValue = null;
                        try
                        {
                            newValue = EvaluateXPathToString(d, xPath, false);
                        }
                        catch (XPathException e)
                        {
                            var errorCell = new XElement(W.tc,
                                                         tc.Elements().Where(z => z.Name != W.p),
                                                         new XElement(W.p,
                                                                      paragraph.Element(W.pPr),
                                                                      CreateRunErrorMessage(e.Message, templateError)));
                            return(errorCell);
                        }

                        var newCell = new XElement(W.tc,
                                                   tc.Elements().Where(z => z.Name != W.p),
                                                   new XElement(W.p,
                                                                paragraph.Element(W.pPr),
                                                                new XElement(W.r,
                                                                             cellRun != null ? cellRun.Element(W.rPr) : new XElement(W.rPr), //if the cell was empty there is no cellrun
                                                                             new XElement(W.t, newValue))));
                        return(newCell);
                    }))),
                                                footerRows
                                                );
                    return(newTable);
                }
                if (element.Name == PA.Conditional)
                {
                    var xPath    = (string)element.Attribute(PA.Select);
                    var match    = (string)element.Attribute(PA.Match);
                    var notMatch = (string)element.Attribute(PA.NotMatch);

                    if (match == null && notMatch == null)
                    {
                        return(CreateContextErrorMessage(element, "Conditional: Must specify either Match or NotMatch", templateError));
                    }

                    if (match != null && notMatch != null)
                    {
                        return(CreateContextErrorMessage(element, "Conditional: Cannot specify both Match and NotMatch", templateError));
                    }

                    string?testValue = null;

                    try
                    {
                        testValue = EvaluateXPathToString(data, xPath, false);
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, e.Message, templateError));
                    }

                    if ((match != null && testValue == match) || (notMatch != null && testValue != notMatch))
                    {
                        var content = element.Elements().Select(e => ContentReplacementTransform(e, data, templateError));
                        return(content);
                    }
                    return(null);
                }
                return(new XElement(element.Name,
                                    element.Attributes(),
                                    element.Nodes().Select(n => ContentReplacementTransform(n, data, templateError))));
            }
            return(node);
        }
示例#17
0
        public void Should_parse_without_line_numbers()
        {
            var result = TemplateError.Parse("Error Message");

            Assert.Equal(new TemplateError("Error Message."), result);
        }
示例#18
0
 private static string FormatError(TemplateError error)
 {
     return($"{(error.Warning ? "Warning" : "Error")} on line {error.Line}, column {error.Column}:" +
            $"{Environment.NewLine}{error.Message}{Environment.NewLine}{Environment.NewLine}");
 }
示例#19
0
        public void Should_return_null_on_parse_when_message_is_empty()
        {
            var result = TemplateError.Parse(string.Empty);

            Assert.Null(result);
        }
        static object ContentReplacementTransform(XNode node, XElement data, TemplateError templateError)
        {
            XElement element = node as XElement;
            if (element != null)
            {
                if (element.Name == PA.Content)
                {
                    XElement para = element.Element(W.p);
                    XElement run = element.Element(W.r);

                    IEnumerable<XObject> selectedData;
                    string xPath = (string)element.Attribute(PA.Select);
                    try
                    {
                        selectedData = ((IEnumerable)data.XPathEvaluate(xPath)).Cast<XObject>();
                    }
                    catch (XPathException e)
                    {
                        var errorRun = CreateRunErrorMessage("XPathException: " + e.Message, templateError);
                        if (para != null)
                            return new XElement(W.p, errorRun);
                        else
                            return errorRun;
                    }
                    if (!selectedData.Any())
                    {
                        var optionalString = (string)element.Attribute(PA.Optional);
                        if (optionalString != null && optionalString.ToLower() == "true")
                        {
                            return null;
                        }
                        else
                        {
                            var errorRun = CreateRunErrorMessage(string.Format("Content XPath expression ({0}) returned no results", xPath), templateError);
                            if (para != null)
                                return new XElement(W.p, errorRun);
                            else
                                return errorRun;
                        }
                    }
                    else if (selectedData.Count() > 1)
                    {
                        var errorRun = CreateRunErrorMessage(string.Format("Content XPath expression ({0}) returned more than one node", xPath), templateError);
                        if (para != null)
                            return new XElement(W.p, errorRun);
                        else
                            return errorRun;
                    }
                    else
                    {
                        string newValue = null;
                        XObject selectedDatum = selectedData.First();
                        if (selectedDatum is XElement)
                            newValue = ((XElement)selectedDatum).Value;
                        else if (selectedDatum is XAttribute)
                            newValue = ((XAttribute)selectedDatum).Value;

                        if (para != null)
                        {
                            return new XElement(W.p,
                                para.Elements(W.pPr),
                                new XElement(W.r,
                                    para.Elements(W.r).Elements(W.rPr).FirstOrDefault(),
                                    new XElement(W.t, newValue)));
                        }
                        else
                        {
                            return new XElement(W.r,
                                run.Elements().Where(e => e.Name != W.t),
                                new XElement(W.t, newValue));
                        }
                    }
                }
                if (element.Name == PA.Repeat)
                {
                    string selector = (string)element.Attribute(PA.Select);
                    IEnumerable<XElement> repeatingData;
                    try
                    {
                        repeatingData = data.XPathSelectElements(selector);
                    }
                    catch (XPathException e)
                    {
                        return CreateParaErrorMessage("XPathException: " + e.Message, templateError);
                    }
                    if (!repeatingData.Any())
                        return CreateParaErrorMessage("Repeat: Select returned no data", templateError);
                    var newContent = repeatingData.Select(d =>
                        {
                            var content = element
                                .Elements()
                                .Select(e => ContentReplacementTransform(e, d, templateError))
                                .ToList();
                            return content;
                        })
                        .ToList();
                    return newContent;
                }
                if (element.Name == PA.Table)
                {
                    IEnumerable<XElement> tableData;
                    try
                    {
                        tableData = data.XPathSelectElements((string)element.Attribute(PA.Select));
                    }
                    catch (XPathException e)
                    {
                        return CreateParaErrorMessage("XPathException: " + e.Message, templateError);
                    }
                    if (tableData.Count() == 0)
                        return CreateParaErrorMessage("Table Select returned no data", templateError);
                    XElement table = element.Element(W.tbl);
                    XElement protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault();
                    if (protoRow == null)
                        return CreateParaErrorMessage(string.Format("Table does not contain a prototype row"), templateError);
                    protoRow.Descendants(W.bookmarkStart).Remove();
                    protoRow.Descendants(W.bookmarkEnd).Remove();
                    XElement newTable = new XElement(W.tbl,
                        table.Elements().Where(e => e.Name != W.tr),
                        table.Elements(W.tr).FirstOrDefault(),
                        tableData.Select(d =>
                            new XElement(W.tr,
                                protoRow.Elements().Where(r => r.Name != W.tc),
                                protoRow.Elements(W.tc)
                                    .Select(tc =>
                                    {
                                        XElement paragraph = tc.Elements(W.p).FirstOrDefault();
                                        XElement cellRun = paragraph.Elements(W.r).FirstOrDefault();
                                        string xPath = paragraph.Value;
                                        IEnumerable<XObject> selectedData;
                                        try
                                        {
                                            selectedData = ((IEnumerable)d.XPathEvaluate(xPath)).Cast<XObject>();
                                        }
                                        catch (XPathException e)
                                        {
                                            XElement errorCell = new XElement(W.tc,
                                                tc.Elements().Where(z => z.Name != W.p),
                                                new XElement(W.p,
                                                    paragraph.Element(W.pPr),
                                                    CreateRunErrorMessage("XPathException: " + e.Message, templateError)));
                                            return errorCell;
                                        }

	                                    if (!selectedData.Any())
	                                    {
			                                var errorRun = CreateRunErrorMessage(string.Format("XPath expression ({0}) returned no results", xPath), templateError);
                                            XElement errorCell = new XElement(W.tc,
                                                tc.Elements().Where(z => z.Name != W.p),
                                                new XElement(W.p,
                                                    paragraph.Element(W.pPr),
                                                    errorRun));
                                            return errorCell;
	                                    }
                                        else if (selectedData.Count() > 1)
                                        {
                                            var errorRun = CreateRunErrorMessage(string.Format("XPath expression ({0}) returned more than one node", xPath), templateError);
                                            XElement errorCell = new XElement(W.tc,
                                                tc.Elements().Where(z => z.Name != W.p),
                                                new XElement(W.p,
                                                    paragraph.Element(W.pPr),
                                                    errorRun));
                                            return errorCell;
                                        }
                                        else
                                        {
                                            string newValue = null;
                                            XObject selectedDatum = selectedData.First();
                                            if (selectedDatum is XElement)
                                                newValue = ((XElement)selectedDatum).Value;
                                            else if (selectedDatum is XAttribute)
                                                newValue = ((XAttribute)selectedDatum).Value;

                                            XElement newCell = new XElement(W.tc,
                                                tc.Elements().Where(z => z.Name != W.p),
                                                new XElement(W.p,
                                                    paragraph.Element(W.pPr),
                                                    new XElement(W.r,
                                                        cellRun.Element(W.rPr),
                                                        new XElement(W.t, newValue))));
                                            return newCell;
                                        }
                                    }))));
                    return newTable;
                }
                if (element.Name == PA.Conditional)
                {
                    IEnumerable<XObject> selectedData;
                    string xPath = (string)element.Attribute(PA.Select);
	                try
	                {
		                selectedData = ((IEnumerable)data.XPathEvaluate(xPath)).Cast<XObject>();
	                }
                    catch (XPathException e)
                    {
                        return CreateParaErrorMessage("XPathException: " + e.Message, templateError);
                    }
                    if (!selectedData.Any())
                    {
                        return CreateParaErrorMessage(string.Format("Conditional XPath expression ({0}) returned no results", xPath), templateError);
                    }
                    else if (selectedData.Count() > 1)
                    {
                        return CreateParaErrorMessage(string.Format("Conditional XPath expression ({0}) returned more than one node", xPath), templateError);
                    }
                    var match = (string)element.Attribute(PA.Match);
                    string testValue = null;
                    XObject selectedDatum = selectedData.First();
                    if (selectedDatum is XElement)
                        testValue = ((XElement)selectedDatum).Value;
                    else if (selectedDatum is XAttribute)
                        testValue = ((XAttribute)selectedDatum).Value;
                    if (testValue == match)
                    {
                        var content = element.Elements().Select(e => ContentReplacementTransform(e, data, templateError));
                        return content;
                    }
                    else
                        return null;
                }
                return new XElement(element.Name,
                    element.Attributes(),
                    element.Nodes().Select(n => ContentReplacementTransform(n, data, templateError)));
            }
            return node;
        }
示例#21
0
        static object ContentReplacementTransform(XNode node, XElement data, TemplateError templateError)
        {
            XElement element = node as XElement;

            if (element != null)
            {
                if (element.Name == PA.Content)
                {
                    XElement para = element.Element(W.p);
                    XElement run  = element.Element(W.r);

                    IEnumerable <XObject> selectedData;
                    string xPath = (string)element.Attribute(PA.Select);
                    try
                    {
                        selectedData = ((IEnumerable)data.XPathEvaluate(xPath)).Cast <XObject>();
                    }
                    catch (XPathException e)
                    {
                        var errorRun = CreateRunErrorMessage("XPathException: " + e.Message, templateError);
                        if (para != null)
                        {
                            return(new XElement(W.p, errorRun));
                        }
                        else
                        {
                            return(errorRun);
                        }
                    }
                    if (!selectedData.Any())
                    {
                        var optionalString = (string)element.Attribute(PA.Optional);
                        if (optionalString != null && optionalString.ToLower() == "true")
                        {
                            return(null);
                        }
                        else
                        {
                            var errorRun = CreateRunErrorMessage(string.Format("Content XPath expression ({0}) returned no results", xPath), templateError);
                            if (para != null)
                            {
                                return(new XElement(W.p, errorRun));
                            }
                            else
                            {
                                return(errorRun);
                            }
                        }
                    }
                    else if (selectedData.Count() > 1)
                    {
                        var errorRun = CreateRunErrorMessage(string.Format("Content XPath expression ({0}) returned more than one node", xPath), templateError);
                        if (para != null)
                        {
                            return(new XElement(W.p, errorRun));
                        }
                        else
                        {
                            return(errorRun);
                        }
                    }
                    else
                    {
                        string  newValue      = null;
                        XObject selectedDatum = selectedData.First();
                        if (selectedDatum is XElement)
                        {
                            newValue = ((XElement)selectedDatum).Value;
                        }
                        else if (selectedDatum is XAttribute)
                        {
                            newValue = ((XAttribute)selectedDatum).Value;
                        }

                        if (para != null)
                        {
                            return(new XElement(W.p,
                                                para.Elements(W.pPr),
                                                new XElement(W.r,
                                                             para.Elements(W.r).Elements(W.rPr).FirstOrDefault(),
                                                             new XElement(W.t, newValue))));
                        }
                        else
                        {
                            return(new XElement(W.r,
                                                run.Elements().Where(e => e.Name != W.t),
                                                new XElement(W.t, newValue)));
                        }
                    }
                }
                if (element.Name == PA.Repeat)
                {
                    string selector = (string)element.Attribute(PA.Select);
                    IEnumerable <XElement> repeatingData;
                    try
                    {
                        repeatingData = data.XPathSelectElements(selector);
                    }
                    catch (XPathException e)
                    {
                        return(CreateParaErrorMessage("XPathException: " + e.Message, templateError));
                    }
                    if (!repeatingData.Any())
                    {
                        return(CreateParaErrorMessage("Repeat: Select returned no data", templateError));
                    }
                    var newContent = repeatingData.Select(d =>
                    {
                        var content = element
                                      .Elements()
                                      .Select(e => ContentReplacementTransform(e, d, templateError))
                                      .ToList();
                        return(content);
                    })
                                     .ToList();
                    return(newContent);
                }
                if (element.Name == PA.Table)
                {
                    IEnumerable <XElement> tableData;
                    try
                    {
                        tableData = data.XPathSelectElements((string)element.Attribute(PA.Select));
                    }
                    catch (XPathException e)
                    {
                        return(CreateParaErrorMessage("XPathException: " + e.Message, templateError));
                    }
                    if (tableData.Count() == 0)
                    {
                        return(CreateParaErrorMessage("Table Select returned no data", templateError));
                    }
                    XElement table    = element.Element(W.tbl);
                    XElement protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault();
                    if (protoRow == null)
                    {
                        return(CreateParaErrorMessage(string.Format("Table does not contain a prototype row"), templateError));
                    }
                    protoRow.Descendants(W.bookmarkStart).Remove();
                    protoRow.Descendants(W.bookmarkEnd).Remove();
                    XElement newTable = new XElement(W.tbl,
                                                     table.Elements().Where(e => e.Name != W.tr),
                                                     table.Elements(W.tr).FirstOrDefault(),
                                                     tableData.Select(d =>
                                                                      new XElement(W.tr,
                                                                                   protoRow.Elements().Where(r => r.Name != W.tc),
                                                                                   protoRow.Elements(W.tc)
                                                                                   .Select(tc =>
                    {
                        XElement paragraph = tc.Elements(W.p).FirstOrDefault();
                        XElement cellRun   = paragraph.Elements(W.r).FirstOrDefault();
                        string xPath       = paragraph.Value;
                        IEnumerable <XObject> selectedData;
                        try
                        {
                            selectedData = ((IEnumerable)d.XPathEvaluate(xPath)).Cast <XObject>();
                        }
                        catch (XPathException e)
                        {
                            XElement errorCell = new XElement(W.tc,
                                                              tc.Elements().Where(z => z.Name != W.p),
                                                              new XElement(W.p,
                                                                           paragraph.Element(W.pPr),
                                                                           CreateRunErrorMessage("XPathException: " + e.Message, templateError)));
                            return(errorCell);
                        }

                        if (!selectedData.Any())
                        {
                            var errorRun       = CreateRunErrorMessage(string.Format("XPath expression ({0}) returned no results", xPath), templateError);
                            XElement errorCell = new XElement(W.tc,
                                                              tc.Elements().Where(z => z.Name != W.p),
                                                              new XElement(W.p,
                                                                           paragraph.Element(W.pPr),
                                                                           errorRun));
                            return(errorCell);
                        }
                        else if (selectedData.Count() > 1)
                        {
                            var errorRun       = CreateRunErrorMessage(string.Format("XPath expression ({0}) returned more than one node", xPath), templateError);
                            XElement errorCell = new XElement(W.tc,
                                                              tc.Elements().Where(z => z.Name != W.p),
                                                              new XElement(W.p,
                                                                           paragraph.Element(W.pPr),
                                                                           errorRun));
                            return(errorCell);
                        }
                        else
                        {
                            string newValue       = null;
                            XObject selectedDatum = selectedData.First();
                            if (selectedDatum is XElement)
                            {
                                newValue = ((XElement)selectedDatum).Value;
                            }
                            else if (selectedDatum is XAttribute)
                            {
                                newValue = ((XAttribute)selectedDatum).Value;
                            }

                            XElement newCell = new XElement(W.tc,
                                                            tc.Elements().Where(z => z.Name != W.p),
                                                            new XElement(W.p,
                                                                         paragraph.Element(W.pPr),
                                                                         new XElement(W.r,
                                                                                      cellRun.Element(W.rPr),
                                                                                      new XElement(W.t, newValue))));
                            return(newCell);
                        }
                    }))));
                    return(newTable);
                }
                if (element.Name == PA.Conditional)
                {
                    IEnumerable <XObject> selectedData;
                    string xPath = (string)element.Attribute(PA.Select);
                    try
                    {
                        selectedData = ((IEnumerable)data.XPathEvaluate(xPath)).Cast <XObject>();
                    }
                    catch (XPathException e)
                    {
                        return(CreateParaErrorMessage("XPathException: " + e.Message, templateError));
                    }
                    if (!selectedData.Any())
                    {
                        return(CreateParaErrorMessage(string.Format("Conditional XPath expression ({0}) returned no results", xPath), templateError));
                    }
                    else if (selectedData.Count() > 1)
                    {
                        return(CreateParaErrorMessage(string.Format("Conditional XPath expression ({0}) returned more than one node", xPath), templateError));
                    }
                    var     match         = (string)element.Attribute(PA.Match);
                    string  testValue     = null;
                    XObject selectedDatum = selectedData.First();
                    if (selectedDatum is XElement)
                    {
                        testValue = ((XElement)selectedDatum).Value;
                    }
                    else if (selectedDatum is XAttribute)
                    {
                        testValue = ((XAttribute)selectedDatum).Value;
                    }
                    if (testValue == match)
                    {
                        var content = element.Elements().Select(e => ContentReplacementTransform(e, data, templateError));
                        return(content);
                    }
                    else
                    {
                        return(null);
                    }
                }
                return(new XElement(element.Name,
                                    element.Attributes(),
                                    element.Nodes().Select(n => ContentReplacementTransform(n, data, templateError))));
            }
            return(node);
        }
示例#22
0
        public void Should_parse_with_open_line_numbers()
        {
            var result = TemplateError.Parse("Error Message at (10:20");

            Assert.Equal(new TemplateError("Error Message at (10:20."), result);
        }
示例#23
0
        public void Should_parse_with_invalid_line_numbers()
        {
            var result = TemplateError.Parse("Error Message at (Test Value)");

            Assert.Equal(new TemplateError("Error Message."), result);
        }
        static object ContentReplacementTransform(XNode node, XElement data, TemplateError templateError)
        {
            XElement element = node as XElement;

            if (element != null)
            {
                if (element.Name == PA.Content)
                {
                    XElement para = element.Descendants(W.p).FirstOrDefault();
                    XElement run  = element.Descendants(W.r).FirstOrDefault();

                    var  xPath          = (string)element.Attribute(PA.Select);
                    var  optionalString = (string)element.Attribute(PA.Optional);
                    bool optional       = (optionalString != null && optionalString.ToLower() == "true");

                    string newValue;
                    try
                    {
                        newValue = EvaluateXPathToString(data, xPath, optional);
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, "XPathException: " + e.Message, templateError));
                    }

                    if (para != null)
                    {
                        XElement p = new XElement(W.p, para.Elements(W.pPr));
                        foreach (string line in newValue.Split('\n'))
                        {
                            p.Add(new XElement(W.r,
                                               para.Elements(W.r).Elements(W.rPr).FirstOrDefault(),
                                               (p.Elements().Count() > 1) ? new XElement(W.br) : null,
                                               new XElement(W.t, line)));
                        }
                        return(p);
                    }
                    else
                    {
                        List <XElement> list = new List <XElement>();
                        foreach (string line in newValue.Split('\n'))
                        {
                            list.Add(new XElement(W.r,
                                                  run.Elements().Where(e => e.Name != W.t),
                                                  (list.Count > 0) ? new XElement(W.br) : null,
                                                  new XElement(W.t, line)));
                        }
                        return(list);
                    }
                }
                if (element.Name == PA.Repeat)
                {
                    string selector       = (string)element.Attribute(PA.Select);
                    var    optionalString = (string)element.Attribute(PA.Optional);
                    bool   optional       = (optionalString != null && optionalString.ToLower() == "true");

                    IEnumerable <XElement> repeatingData;
                    try
                    {
                        repeatingData = data.XPathSelectElements(selector);
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, "XPathException: " + e.Message, templateError));
                    }
                    if (!repeatingData.Any())
                    {
                        if (optional)
                        {
                            return(null);
                            //XElement para = element.Descendants(W.p).FirstOrDefault();
                            //if (para != null)
                            //    return new XElement(W.p, new XElement(W.r));
                            //else
                            //    return new XElement(W.r);
                        }
                        return(CreateContextErrorMessage(element, "Repeat: Select returned no data", templateError));
                    }
                    var newContent = repeatingData.Select(d =>
                    {
                        var content = element
                                      .Elements()
                                      .Select(e => ContentReplacementTransform(e, d, templateError))
                                      .ToList();
                        return(content);
                    })
                                     .ToList();
                    return(newContent);
                }
                if (element.Name == PA.Table)
                {
                    IEnumerable <XElement> tableData;
                    try
                    {
                        tableData = data.XPathSelectElements((string)element.Attribute(PA.Select));
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, "XPathException: " + e.Message, templateError));
                    }
                    if (tableData.Count() == 0)
                    {
                        return(CreateContextErrorMessage(element, "Table Select returned no data", templateError));
                    }
                    XElement table    = element.Element(W.tbl);
                    XElement protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault();
                    var      footerRowsBeforeTransform = table
                                                         .Elements(W.tr)
                                                         .Skip(2)
                                                         .ToList();
                    var footerRows = footerRowsBeforeTransform
                                     .Select(x => ContentReplacementTransform(x, data, templateError))
                                     .ToList();
                    if (protoRow == null)
                    {
                        return(CreateContextErrorMessage(element, string.Format("Table does not contain a prototype row"), templateError));
                    }
                    protoRow.Descendants(W.bookmarkStart).Remove();
                    protoRow.Descendants(W.bookmarkEnd).Remove();
                    XElement newTable = new XElement(W.tbl,
                                                     table.Elements().Where(e => e.Name != W.tr),
                                                     table.Elements(W.tr).FirstOrDefault(),
                                                     tableData.Select(d =>
                                                                      new XElement(W.tr,
                                                                                   protoRow.Elements().Where(r => r.Name != W.tc),
                                                                                   protoRow.Elements(W.tc)
                                                                                   .Select(tc =>
                    {
                        XElement paragraph  = tc.Elements(W.p).FirstOrDefault();
                        XElement cellRun    = paragraph.Elements(W.r).FirstOrDefault();
                        string xPath        = paragraph.Value;
                        bool cellIsOptional = false;

                        // There is probably a much better way of doing this,
                        // similar to the ContentReplacementTransform used for the footer
                        // but it means you probably couldn't use the simple xpath text
                        // and you would need to always use <Content/> tag in each cell!
                        TableCellContent(paragraph.Value, out xPath, out cellIsOptional);

                        string newValue = null;
                        try
                        {
                            newValue = EvaluateXPathToString(d, xPath, cellIsOptional);
                        }
                        catch (XPathException e)
                        {
                            XElement errorCell = new XElement(W.tc,
                                                              tc.Elements().Where(z => z.Name != W.p),
                                                              new XElement(W.p,
                                                                           paragraph.Element(W.pPr),
                                                                           CreateRunErrorMessage(e.Message, templateError)));
                            return(errorCell);
                        }

                        XElement newCell = new XElement(W.tc,
                                                        tc.Elements().Where(z => z.Name != W.p),
                                                        new XElement(W.p,
                                                                     paragraph.Element(W.pPr),
                                                                     new XElement(W.r,
                                                                                  cellRun != null ? cellRun.Element(W.rPr) : new XElement(W.rPr), //if the cell was empty there is no cellrun
                                                                                  new XElement(W.t, newValue))));
                        return(newCell);
                    }))),
                                                     footerRows
                                                     );
                    return(newTable);
                }
                if (element.Name == PA.Conditional)
                {
                    string xPath    = (string)element.Attribute(PA.Select);
                    var    match    = (string)element.Attribute(PA.Match);
                    var    notMatch = (string)element.Attribute(PA.NotMatch);

                    if (match == null && notMatch == null)
                    {
                        return(CreateContextErrorMessage(element, "Conditional: Must specify either Match or NotMatch", templateError));
                    }
                    if (match != null && notMatch != null)
                    {
                        return(CreateContextErrorMessage(element, "Conditional: Cannot specify both Match and NotMatch", templateError));
                    }

                    string testValue = null;

                    try
                    {
                        testValue = EvaluateXPathToString(data, xPath, false);
                    }
                    catch (XPathException e)
                    {
                        return(CreateContextErrorMessage(element, e.Message, templateError));
                    }

                    if ((match != null && testValue == match) || (notMatch != null && testValue != notMatch))
                    {
                        var content = element.Elements().Select(e => ContentReplacementTransform(e, data, templateError));
                        return(content);
                    }
                    return(null);
                }
                return(new XElement(element.Name,
                                    element.Attributes(),
                                    element.Nodes().Select(n => ContentReplacementTransform(n, data, templateError))));
            }
            return(node);
        }
 private static XElement CreateParaErrorMessage(string errorMessage, TemplateError templateError)
 {
     templateError.HasError = true;
     var errorPara = new XElement(W.p,
         new XElement(W.r,
             new XElement(W.rPr,
                 new XElement(W.color, new XAttribute(W.val, "FF0000")),
                 new XElement(W.highlight, new XAttribute(W.val, "yellow"))),
                 new XElement(W.t, errorMessage)));
     return errorPara;
 }
        private static object CreateContextErrorMessage(XElement element, string errorMessage, TemplateError templateError)
        {
            XElement para     = element.Descendants(W.p).FirstOrDefault();
            XElement run      = element.Descendants(W.r).FirstOrDefault();
            var      errorRun = CreateRunErrorMessage(errorMessage, templateError);

            if (para != null)
            {
                return(new XElement(W.p, errorRun));
            }
            else
            {
                return(errorRun);
            }
        }
        // The following method is written using tree modification, not RPFT, because it is easier to write in this fashion.
        // These types of operations are not as easy to write using RPFT.
        // Unless you are completely clear on the semantics of LINQ to XML DML, do not make modifications to this method.
        private static void NormalizeTablesRepeatAndConditional(XElement xDoc, TemplateError te)
        {
            var tables = xDoc.Descendants(PA.Table).ToList();
            foreach (var table in tables)
            {
                var followingElement = table.ElementsAfterSelf().Where(e => e.Name == W.tbl || e.Name == W.p).FirstOrDefault();
                if (followingElement == null || followingElement.Name != W.tbl)
                {
                    table.ReplaceWith(CreateParaErrorMessage("Table metadata is not immediately followed by a table", te));
                    continue;
                }
                // remove superflous paragraph from Table metadata
                table.RemoveNodes();
                // detach w:tbl from parent, and add to Table metadata
                followingElement.Remove();
                table.Add(followingElement);
            }

            int repeatDepth = 0;
            int conditionalDepth = 0;
            foreach (var metadata in xDoc.Descendants().Where(d =>
                    d.Name == PA.Repeat ||
                    d.Name == PA.Conditional ||
                    d.Name == PA.EndRepeat ||
                    d.Name == PA.EndConditional))
            {
                if (metadata.Name == PA.Repeat)
                {
                    ++repeatDepth;
                    metadata.Add(new XAttribute(PA.Depth, repeatDepth));
                    continue;
                }
                if (metadata.Name == PA.EndRepeat)
                {
                    metadata.Add(new XAttribute(PA.Depth, repeatDepth));
                    --repeatDepth;
                    continue;
                }
                if (metadata.Name == PA.Conditional)
                {
                    ++conditionalDepth;
                    metadata.Add(new XAttribute(PA.Depth, conditionalDepth));
                    continue;
                }
                if (metadata.Name == PA.EndConditional)
                {
                    metadata.Add(new XAttribute(PA.Depth, conditionalDepth));
                    --conditionalDepth;
                    continue;
                }
            }

            while (true)
            {
                bool didReplace = false;
                foreach (var metadata in xDoc.Descendants().Where(d => (d.Name == PA.Repeat || d.Name == PA.Conditional) && d.Attribute(PA.Depth) != null).ToList())
                {
                    var depth = (int)metadata.Attribute(PA.Depth);
                    XName matchingEndName = null;
                    if (metadata.Name == PA.Repeat)
                        matchingEndName = PA.EndRepeat;
                    else if (metadata.Name == PA.Conditional)
                        matchingEndName = PA.EndConditional;
                    if (matchingEndName == null)
                        throw new OpenXmlPowerToolsException("Internal error");
                    var matchingEnd = metadata.ElementsAfterSelf(matchingEndName).FirstOrDefault(end => { return (int)end.Attribute(PA.Depth) == depth; });
                    if (matchingEnd == null)
                    {
                        metadata.ReplaceWith(CreateParaErrorMessage(string.Format("{0} does not have matching {1}", metadata.Name.LocalName, matchingEndName.LocalName), te));
                        continue;
                    }
                    metadata.RemoveNodes();
                    var contentBetween = metadata.ElementsAfterSelf().TakeWhile(after => after != matchingEnd).ToList();
                    contentBetween.DescendantsAndSelf(W.bookmarkStart).Remove();
                    contentBetween.DescendantsAndSelf(W.bookmarkEnd).Remove();
                    foreach (var item in contentBetween)
                        item.Remove();
                    metadata.Add(contentBetween);
                    metadata.Attributes(PA.Depth).Remove();
                    matchingEnd.Remove();
                    didReplace = true;
                    break;
                }
                if (!didReplace)
                    break;
            }
        }
        private static object TransformToMetadata(XNode node, XElement data, TemplateError te)
        {
            XElement element = node as XElement;
            if (element != null)
            {
                if (element.Name == W.p)
                {
                    var paraContents = element
                        .DescendantsTrimmed(W.txbxContent)
                        .Where(e => e.Name == W.t)
                        .Select(t => (string)t)
                        .StringConcatenate()
                        .Trim();
                    int occurances = paraContents.Select((c, i) => paraContents.Substring(i)).Count(sub => sub.StartsWith("<#"));
                    if (paraContents.StartsWith("<#") && paraContents.EndsWith("#>") && occurances == 1)
                    {
                        var xmlText = paraContents.Substring(2, paraContents.Length - 4).Trim();
                        XElement xml;
                        try
                        {
                            xml = XElement.Parse(xmlText);
                        }
                        catch (XmlException e)
                        {
                            return CreateParaErrorMessage("XmlException: " + e.Message, te);
                        }
                        string schemaError = ValidatePerSchema(xml);
                        if (schemaError != null)
                            return CreateParaErrorMessage("Schema Validation Error: " + schemaError, te);
                        xml.Add(element);
                        return xml;
                    }
                    if (paraContents.Contains("<#"))
                    {
                        List<RunReplacementInfo> runReplacementInfo = new List<RunReplacementInfo>();
                        var thisGuid = Guid.NewGuid().ToString();
                        var r = new Regex("<#.*?#>");
                        XElement xml = null;
                        OpenXmlRegex.Replace(new[] { element }, r, thisGuid, (para, match) =>
                        {
                            var matchString = match.Value.Trim();
                            var xmlText = matchString.Substring(2, matchString.Length - 4).Trim().Replace('“', '"').Replace('”', '"');
                            try
                            {
                                xml = XElement.Parse(xmlText);
                            }
                            catch (XmlException e)
                            {
                                RunReplacementInfo rri = new RunReplacementInfo()
                                {
                                    Xml = null,
                                    XmlExceptionMessage = "XmlException: " + e.Message,
                                    SchemaValidationMessage = null,
                                };
                                runReplacementInfo.Add(rri);
                                return true;
                            }
                            string schemaError = ValidatePerSchema(xml);
                            if (schemaError != null)
                            {
                                RunReplacementInfo rri = new RunReplacementInfo()
                                {
                                    Xml = null,
                                    XmlExceptionMessage = null,
                                    SchemaValidationMessage = "Schema Validation Error: " + schemaError,
                                };
                                runReplacementInfo.Add(rri);
                                return true;
                            }
                            RunReplacementInfo rri2 = new RunReplacementInfo()
                            {
                                Xml = xml,
                                XmlExceptionMessage = null,
                                SchemaValidationMessage = null,
                            };
                            runReplacementInfo.Add(rri2);
                            return true;
                        }, false);

                        var newPara = new XElement(element);
                        foreach (var rri in runReplacementInfo)
                        {
                            var runToReplace = newPara.Descendants(W.r).FirstOrDefault(rn => rn.Value == thisGuid && rn.Parent.Name != PA.Content);
                            if (runToReplace == null)
                                throw new OpenXmlPowerToolsException("Internal error");
                            if (rri.XmlExceptionMessage != null)
                                runToReplace.ReplaceWith(CreateRunErrorMessage(rri.XmlExceptionMessage, te));
                            else if (rri.SchemaValidationMessage != null)
                                runToReplace.ReplaceWith(CreateRunErrorMessage(rri.SchemaValidationMessage, te));
                            else
                            {
                                var newXml = new XElement(rri.Xml);
                                newXml.Add(runToReplace);
                                runToReplace.ReplaceWith(newXml);
                            }
                        }
                        var coalescedParagraph = WordprocessingMLUtil.CoalesceAdjacentRunsWithIdenticalFormatting(newPara);
                        return coalescedParagraph;
                    }
                }

                return new XElement(element.Name,
                    element.Attributes(),
                    element.Nodes().Select(n => TransformToMetadata(n, data, te)));
            }
            return node;
        }
示例#29
0
        public void Should_extract_line_number_only()
        {
            var result = TemplateError.Parse("Error at (10)");

            Assert.Equal(new TemplateError("Error.", 10), result);
        }