/// <summary> /// Handle the related attribute types which exist upon the element exposed by the given context, if any. /// </summary> /// <returns>A response type providing information about the result of this operation.</returns> /// <param name="context">The rendering context, which exposes a ZPT element.</param> public AttributeHandlingResult Handle(IRenderingContext context) { if(context == null) { throw new ArgumentNullException(nameof(context)); } IRenderingContext[] output = null; var attribute = context.GetTalAttribute(ZptConstants.Tal.RepeatAttribute); if(attribute != null) { string repeatVariableName, expression; this.ParseAttributeValue(attribute, out repeatVariableName, out expression, context.Element); var sequence = this.GetSequence(expression, context.TalModel, context); if(sequence != null) { var repetitionInfos = this.GetRepetitions(sequence, context.Element, repeatVariableName); output = this.HandleRepetitions(repetitionInfos, context); } } if(output == null) { output = new [] { context }; } return new AttributeHandlingResult(output, true); }
/// <summary> /// Handle the related attribute types which exist upon the element exposed by the given context, if any. /// </summary> /// <returns>A response type providing information about the result of this operation.</returns> /// <param name="context">The rendering context, which exposes a ZPT element.</param> public AttributeHandlingResult Handle(IRenderingContext context) { if(context == null) { throw new ArgumentNullException(nameof(context)); } AttributeHandlingResult output; var attrib = context.GetTalAttribute(ZptConstants.Tal.OmitTagAttribute); if(attrib != null) { if(attrib.Value.Length == 0) { var children = context.Element.Omit(); output = new AttributeHandlingResult(new RenderingContext[0], false, children.Select(x => context.CreateSiblingContext(x)).ToArray()); } else { // Normal handling by detecting an attribute and using its value var result = context.TalModel.Evaluate(attrib.Value, context); if(!result.CancelsAction && result.GetValueAsBoolean()) { var children = context.Element.Omit(); output = new AttributeHandlingResult(new RenderingContext[0], false, children.Select(x => context.CreateSiblingContext(x)).ToArray()); } else { output = new AttributeHandlingResult(new [] { context }, true); } } } else { output = new AttributeHandlingResult(new [] { context }, true); } return output; }
/// <summary> /// Handle the related attribute types which exist upon the element exposed by the given context, if any. /// </summary> /// <returns>A response type providing information about the result of this operation.</returns> /// <param name="context">The rendering context, which exposes a ZPT element.</param> public AttributeHandlingResult Handle(IRenderingContext context) { if(context == null) { throw new ArgumentNullException(nameof(context)); } AttributeHandlingResult output; var attrib = context.GetTalAttribute(ZptConstants.Tal.OnErrorAttribute); if(attrib != null) { string mode; var expressionResult = this.GetAttributeResult(attrib, context, out mode); if(expressionResult.CancelsAction) { output = new AttributeHandlingResult(new [] { context }, true); } else if(expressionResult.Value == null) { context.Element.RemoveAllChildren(); output = new AttributeHandlingResult(new [] { context }, true); } else { context.Element.ReplaceChildrenWith(expressionResult.GetValue<string>(), mode == STRUCTURE_INDICATOR); output = new AttributeHandlingResult(new [] { context }, true); } ZptConstants.TraceSource.TraceInformation(Resources.LogMessageFormats.TalErrorHandled, context.Element.GetFullFilePathAndLocation(), nameof(OnErrorAttributeHandler), nameof(Handle)); } else { output = new AttributeHandlingResult(new [] { context }, true); } return output; }
/// <summary> /// Handle the related attribute types which exist upon the element exposed by the given context, if any. /// </summary> /// <returns>A response type providing information about the result of this operation.</returns> /// <param name="context">The rendering context, which exposes a ZPT element.</param> public AttributeHandlingResult Handle(IRenderingContext context) { if(context == null) { throw new ArgumentNullException(nameof(context)); } AttributeHandlingResult output = new AttributeHandlingResult(new [] { context }, true); var attribute = context.GetTalAttribute(ZptConstants.Tal.ConditionAttribute); if(attribute != null) { ExpressionResult result; try { result = context.TalModel.Evaluate(attribute.Value, context); } catch(Exception ex) { string message = String.Format(ExceptionMessages.ExpressionEvaluationException, ZptConstants.Tal.Namespace, ZptConstants.Tal.ConditionAttribute, attribute.Value, context.Element.Name); throw new ModelEvaluationException(message, ex) { ExpressionText = attribute.Value, ElementName = context.Element.Name, }; } var removeElement = result.CancelsAction? false : !result.GetValueAsBoolean(); if(removeElement) { context.Element.Remove(); output = new AttributeHandlingResult(new RenderingContext[0], false); } } return output; }
/// <summary> /// Visit the given context, as well as its child contexts, and return a collection of the resultant contexts. /// </summary> /// <remarks> /// <para> /// This operation performs the same work as <see cref="Visit"/>, but it then visits all of the resultant contexts, /// recursively moving down the exposed document tree, visiting each context in turn. /// </para> /// <para> /// In this implementation, the visit additionally provides error-handling via the TAL on-error attribute. /// </para> /// </remarks> /// <returns>Zero or more <see cref="RenderingContext"/> instances, determined by the outcome of this visit.</returns> /// <param name="context">The rendering context to visit.</param> public override IRenderingContext[] VisitRecursively(IRenderingContext context) { IRenderingContext[] output; try { output = base.VisitRecursively(context); } catch(RenderingException ex) { output = new [] { context }; if(context.GetTalAttribute(ZptConstants.Tal.OnErrorAttribute) != null) { context.TalModel.AddError(ex); _errorHandler.Handle(context); } else { throw; } } return output; }
/// <summary> /// Handle the related attribute types which exist upon the element exposed by the given context, if any. /// </summary> /// <returns>A response type providing information about the result of this operation.</returns> /// <param name="context">The rendering context, which exposes a ZPT element.</param> public AttributeHandlingResult Handle(IRenderingContext context) { if(context == null) { throw new ArgumentNullException(nameof(context)); } var attrib = context.GetTalAttribute(ZptConstants.Tal.AttributesAttribute); if(attrib != null) { var itemMatches = ItemMatcher .Matches(attrib.Value) .Cast<Match>() .Select(x => Attribute.Match(x.Groups[1].Value)); if(itemMatches.Any(x => !x.Success)) { string message = String.Format(Resources.ExceptionMessages.ZptAttributeParsingError, ZptConstants.Tal.Namespace, ZptConstants.Tal.AttributesAttribute, attrib.Value); throw new ParserException(message) { SourceElementName = context.Element.Name, SourceAttributeName = attrib.Name, SourceAttributeValue = attrib.Value }; } var items = itemMatches .Select(x => new { Prefix = x.Groups[1].Value, AttributeName = x.Groups[2].Value, Expression = x.Groups[3].Value }) .ToArray(); foreach(var item in items) { ExpressionResult result; var unescapedExpression = this.UnescapeSemicolons(item.Expression); try { result = context.TalModel.Evaluate(unescapedExpression, context); } catch(Exception ex) { string message = String.Format(Resources.ExceptionMessages.ExpressionEvaluationException, ZptConstants.Tal.Namespace, ZptConstants.Tal.AttributesAttribute, item.Expression, context.Element.Name); throw new ModelEvaluationException(message, ex) { ExpressionText = item.Expression, ElementName = context.Element.Name, }; } if(!result.CancelsAction) { var nspace = new ZptNamespace(prefix: item.Prefix); if(result.Value == null) { if(String.IsNullOrEmpty(item.Prefix)) { context.Element.RemoveAttribute(item.AttributeName); } else { context.Element.RemoveAttribute(nspace, item.AttributeName); } } else { if(String.IsNullOrEmpty(item.Prefix)) { context.Element.SetAttribute(item.AttributeName, result.Value.ToString()); } else { context.Element.SetAttribute(nspace, item.AttributeName, result.Value.ToString()); } } } } } return new AttributeHandlingResult(new [] { context }, true); }
/// <summary> /// Gets either the TAL 'content' or 'replace' attribute from the given element. /// </summary> /// <returns>The attribute, or a <c>null</c> reference.</returns> /// <param name="context">The rendering context.</param> /// <param name="attribName">Exposes the name of the attribute.</param> private IZptAttribute GetAttribute(IRenderingContext context, out string attribName) { IZptAttribute contentAttrib = context.GetTalAttribute(ZptConstants.Tal.ContentAttribute), replaceAttrib = context.GetTalAttribute(ZptConstants.Tal.ReplaceAttribute), output; if(contentAttrib != null && replaceAttrib != null) { string message = String.Format(ExceptionMessages.ContentAndReplaceAttributesCannotCoexist, context.Element.Name); throw new ParserException(message) { SourceElementName = context.Element.Name }; } else if(contentAttrib != null) { output = contentAttrib; attribName = ZptConstants.Tal.ContentAttribute; } else { output = replaceAttrib; attribName = ZptConstants.Tal.ReplaceAttribute; } return output; }