public static XElement LoadStream(XmlReader reader, XName rootName, params XName[] streamNames) { ArgumentNullException.ThrowIfNull(reader); ArgumentNullException.ThrowIfNull(rootName); ArgumentNullException.ThrowIfNull(streamNames); for (int i = 0; i < streamNames.Length; i++) { if (streamNames[i] == null) { throw new ArgumentNullException("streamNames[" + i + "]"); } } if (reader.MoveToContent() != XmlNodeType.Element) { throw new InvalidOperationException(string.Format("The reader should be on a node of type '{0}'.", XmlNodeType.Element)); } XElement source = new XElement(rootName); StreamLoader loader = new StreamLoader(reader, streamNames); XName streamName = streamNames.Length > 0 ? streamNames[0] : null; loader.ReadElementUntil(source, streamName); if (streamName != null) { source.AddAnnotation(loader); } return(source); }
/// <summary> /// Adds UVML annotations to the specified UVML element tree. /// </summary> /// <param name="dataSourceTypeName">The name of the data source wrapper associated with this tree.</param> /// <param name="root">The root of the UVML element tree to annotate.</param> public static void AddUvmlAnnotations(String dataSourceTypeName, XElement root) { Contract.RequireNotEmpty(dataSourceTypeName, nameof(dataSourceTypeName)); Contract.Require(root, nameof(root)); var templates = 0; if (root.Annotation<UvmlMetadataAnnotation>() != null) return; root.AddAnnotation(new UvmlMetadataAnnotation()); AddUvmlAnnotations(dataSourceTypeName, root, ref templates); }
private static XObject CloneWithAnnotation(XNode node) { XElement element = node as XElement; if (element != null) { XElement newElement = new XElement(element.Name, element.Attributes(), element.Nodes().Select(n => CloneWithAnnotation(n))); if (element.Annotation<MatchSemaphore>() != null) newElement.AddAnnotation(element.Annotation<MatchSemaphore>()); } return node; }
public static ASupportElement GetInstance(XElement definition) { Type eType = ElementType (definition); if (eType != null) { if (definition.Annotation (eType) != null) return definition.Annotation (eType) as ASupportElement; else { var instance = Activator.CreateInstance (eType, new object[] { definition }); definition.AddAnnotation (instance); return instance as ASupportElement; } } else return null; }
public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { var record = (ConstructorParameterTypeRecord)((BamlRecordNode)node).Record; var elem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml)); elem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension var bamlElem = new BamlElement(node); bamlElem.Xaml = elem; parent.Xaml.Element.Add(elem); var type = ctx.ResolveType(record.TypeId); var typeName = ctx.ToString(parent.Xaml, type); elem.Add(new XElement(ctx.GetPseudoName("Ctor"), typeName)); return bamlElem; }
public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) { var record = (DefAttributeKeyTypeRecord)((BamlRecordNode)node).Record; var type = ctx.ResolveType(record.TypeId); var typeName = ctx.ToString(parent.Xaml, type); var key = (XamlResourceKey)node.Annotation; var bamlElem = new BamlElement(node); bamlElem.Xaml = new XElement(ctx.GetXamlNsName("Key", parent.Xaml)); parent.Xaml.Element.Add(bamlElem.Xaml.Element); var typeElem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml)); typeElem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), typeName)); bamlElem.Xaml.Element.Add(typeElem); key.KeyElement = bamlElem; return bamlElem; }
public void AddEventXElementShouldBeNotifiedWithAnnotations() { var el = new XElement("test"); bool changedNotification = false; var handler = new EventHandler<XObjectChangeEventArgs>( (sender, cea) => { changedNotification = true; } ); el.AddAnnotation(new object()); el.Changed += handler; var child = new XElement("test2"); el.Add(child); Assert.True(changedNotification); changedNotification = false; child.Add(new XAttribute("a", "b")); Assert.True(changedNotification); }
public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { var record = (PropertyTypeReferenceRecord)((BamlRecordNode)node).Record; var attr = ctx.ResolveProperty(record.AttributeId); var type = ctx.ResolveType(record.TypeId); var typeName = ctx.ToString(parent.Xaml, type); var elem = new BamlElement(node); var elemAttr = ctx.ResolveProperty(record.AttributeId); elem.Xaml = new XElement(elemAttr.ToXName(ctx, null)); elem.Xaml.Element.AddAnnotation(elemAttr); parent.Xaml.Element.Add(elem.Xaml.Element); var typeElem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml)); typeElem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), typeName)); elem.Xaml.Element.Add(typeElem); elemAttr.DeclaringType.ResolveNamespace(elem.Xaml, ctx); elem.Xaml.Element.Name = elemAttr.ToXName(ctx, null); return elem; }
private static object ProcessHyperlinkToBookmark(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element) { var style = new Dictionary<string, string>(); var a = new XElement(Xhtml.a, new XAttribute("href", "#" + (string) element.Attribute(W.anchor)), element.Elements(W.r).Select(run => ConvertRun(wordDoc, settings, run))); style.Add("text-decoration", "none"); a.AddAnnotation(style); return a; }
private static object CreateBorderDivs(WordprocessingDocument wordDoc, HtmlConverterSettings settings, IEnumerable<XElement> elements) { return elements.GroupAdjacent(e => { var pBdr = e.Elements(W.pPr).Elements(W.pBdr).FirstOrDefault(); if (pBdr != null) { var indStr = string.Empty; var ind = e.Elements(W.pPr).Elements(W.ind).FirstOrDefault(); if (ind != null) indStr = ind.ToString(SaveOptions.DisableFormatting); return pBdr.ToString(SaveOptions.DisableFormatting) + indStr; } return e.Name == W.tbl ? "table" : string.Empty; }) .Select(g => { if (g.Key == string.Empty) { return (object) GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, 0m); } if (g.Key == "table") { return g.Select(gc => ConvertToHtmlTransform(wordDoc, settings, gc, false, 0)); } var pPr = g.First().Elements(W.pPr).First(); var pBdr = pPr.Element(W.pBdr); var style = new Dictionary<string, string>(); GenerateBorderStyle(pBdr, W.top, style, BorderType.Paragraph); GenerateBorderStyle(pBdr, W.right, style, BorderType.Paragraph); GenerateBorderStyle(pBdr, W.bottom, style, BorderType.Paragraph); GenerateBorderStyle(pBdr, W.left, style, BorderType.Paragraph); var currentMarginLeft = 0m; var ind = pPr.Element(W.ind); if (ind != null) { var leftInInches = (decimal?) ind.Attribute(W.left)/1440m ?? 0; var hangingInInches = -(decimal?) ind.Attribute(W.hanging)/1440m ?? 0; currentMarginLeft = leftInInches + hangingInInches; style.AddIfMissing("margin-left", currentMarginLeft > 0m ? string.Format(NumberFormatInfo.InvariantInfo, "{0:0.00}in", currentMarginLeft) : "0"); } var div = new XElement(Xhtml.div, GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, currentMarginLeft)); div.AddAnnotation(style); return div; }) .ToList(); }
/* * Handle: * - b * - bdr * - caps * - color * - dstrike * - highlight * - i * - position * - rFonts * - shd * - smallCaps * - spacing * - strike * - sz * - u * - vanish * - vertAlign * * Don't handle: * - em * - emboss * - fitText * - imprint * - kern * - outline * - shadow * - w * */ private static object ConvertRun(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement run) { var rPr = run.Element(W.rPr); if (rPr == null) return run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m)); // hide all content that contains the w:rPr/w:webHidden element if (rPr.Element(W.webHidden) != null) return null; var style = DefineRunStyle(run); object content = run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m)); // Wrap content in h:sup or h:sub elements as necessary. if (rPr.Element(W.vertAlign) != null) { XElement newContent = null; var vertAlignVal = (string)rPr.Elements(W.vertAlign).Attributes(W.val).FirstOrDefault(); switch (vertAlignVal) { case "superscript": newContent = new XElement(Xhtml.sup, content); break; case "subscript": newContent = new XElement(Xhtml.sub, content); break; } if (newContent != null && newContent.Nodes().Any()) content = newContent; } var langAttribute = GetLangAttribute(run); XEntity runStartMark; XEntity runEndMark; DetermineRunMarks(run, rPr, style, out runStartMark, out runEndMark); if (style.Any() || langAttribute != null || runStartMark != null) { style.AddIfMissing("margin", "0"); style.AddIfMissing("padding", "0"); var xe = new XElement(Xhtml.span, langAttribute, runStartMark, content, runEndMark); xe.AddAnnotation(style); content = xe; } return content; }
private static List<object> TransformElementsPrecedingTab(WordprocessingDocument wordDoc, HtmlConverterSettings settings, List<XElement> elementsPrecedingTab, XElement firstTabRun) { var tabWidth = firstTabRun != null ? (decimal?) firstTabRun.Elements(W.tab).Attributes(PtOpenXml.TabWidth).FirstOrDefault() ?? 0m : 0m; var precedingElementsWidth = elementsPrecedingTab .Elements() .Where(c => c.Attributes(PtOpenXml.TabWidth).Any()) .Select(e => (decimal) e.Attribute(PtOpenXml.TabWidth)) .Sum(); var totalWidth = precedingElementsWidth + tabWidth; var txElementsPrecedingTab = elementsPrecedingTab .Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m)) .ToList(); if (txElementsPrecedingTab.Count > 1) { var span = new XElement(Xhtml.span, txElementsPrecedingTab); var spanStyle = new Dictionary<string, string> { { "display", "inline-block" }, { "text-indent", "0" }, { "width", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}in", totalWidth) } }; span.AddAnnotation(spanStyle); } else if (txElementsPrecedingTab.Count == 1) { var element = txElementsPrecedingTab.First() as XElement; if (element != null) { var spanStyle = element.Annotation<Dictionary<string, string>>(); spanStyle.AddIfMissing("display", "inline-block"); spanStyle.AddIfMissing("text-indent", "0"); spanStyle.AddIfMissing("width", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}in", totalWidth)); } } return txElementsPrecedingTab; }
// typeScope is applied for child items, rather than obj itself. private XElement SerializeXElement(object obj, Type defaultType, XName name, SerializationScope typeScope) { Debug.Assert(obj != null && defaultType != null && name != null); var objType = obj.GetType(); var objTypeName = _Builder.GlobalScope.GetName(objType); if (objTypeName == null) throw new NotSupportedException(string.Format(Prompts.UnregisteredType, objType, _Builder.GlobalScope)); var s = _Builder.GetSerializer(objType); var e = new XElement(name); //如果名义类型和实际类型不同,则注明实际类型。 //如果是 TypeScope 中未定义的类型,则使用对应的元素名,而不使用 xsi:type if (name != objTypeName && objType != defaultType) { //先将 XName 加入批注,到根节点中处理。 e.AddAnnotation(objTypeName); } //一般不会调用到此处,除非 obj 是根部节点,或是集合中的一项。 if (s == null) throw new NotSupportedException(string.Format(Prompts.UnregisteredType, objType, typeScope)); EnterObjectSerialization(obj); s.Serialize(e, obj, this, typeScope); ExitObjectSerialization(obj); return e; }
private static object ProcessTableRow(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element, decimal currentMarginLeft) { var style = new Dictionary<string, string>(); int? trHeight = (int?) element.Elements(W.trPr).Elements(W.trHeight).Attributes(W.val).FirstOrDefault(); if (trHeight != null) style.AddIfMissing("height", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.00}in", (decimal) trHeight/1440m)); var htmlRow = new XElement(Xhtml.tr, element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft))); if (style.Any()) htmlRow.AddAnnotation(style); return htmlRow; }
private static object ProcessTable(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element, decimal currentMarginLeft) { var style = new Dictionary<string, string>(); style.AddIfMissing("border-collapse", "collapse"); style.AddIfMissing("border", "none"); var bidiVisual = element.Elements(W.tblPr).Elements(W.bidiVisual).FirstOrDefault(); var tblW = element.Elements(W.tblPr).Elements(W.tblW).FirstOrDefault(); if (tblW != null) { var type = (string)tblW.Attribute(W.type); if (type != null && type == "pct") { var w = (int)tblW.Attribute(W._w); style.AddIfMissing("width", (w / 50) + "%"); } } var tblInd = element.Elements(W.tblPr).Elements(W.tblInd).FirstOrDefault(); if (tblInd != null) { var tblIndType = (string)tblInd.Attribute(W.type); if (tblIndType != null) { if (tblIndType == "dxa") { var width = (decimal?)tblInd.Attribute(W._w); if (width != null) { style.AddIfMissing("margin-left", width > 0m ? string.Format(NumberFormatInfo.InvariantInfo, "{0}pt", width / 20m) : "0"); } } } } var tableDirection = bidiVisual != null ? new XAttribute("dir", "rtl") : new XAttribute("dir", "ltr"); style.AddIfMissing("margin-bottom", ".001pt"); var table = new XElement(Xhtml.table, // TODO: Revisit and make sure the omission is covered by appropriate CSS. // new XAttribute("border", "1"), // new XAttribute("cellspacing", 0), // new XAttribute("cellpadding", 0), tableDirection, element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft))); table.AddAnnotation(style); var jc = (string)element.Elements(W.tblPr).Elements(W.jc).Attributes(W.val).FirstOrDefault() ?? "left"; XAttribute dir = null; XAttribute jcToUse = null; if (bidiVisual != null) { dir = new XAttribute("dir", "rtl"); if (jc == "left") jcToUse = new XAttribute("align", "right"); else if (jc == "right") jcToUse = new XAttribute("align", "left"); else if (jc == "center") jcToUse = new XAttribute("align", "center"); } else { jcToUse = new XAttribute("align", jc); } var tableDiv = new XElement(Xhtml.div, dir, jcToUse, table); return tableDiv; }
public Place ObjectToElement(INakedObjectAdapter nakedObjectAdapter) { Log.Debug("objectToElement(" + DoLog("object", nakedObjectAdapter) + ")"); var nos = (IObjectSpec) nakedObjectAdapter.Spec; Log.Debug("objectToElement(NO): create element and nof:title"); XElement element = Schema.CreateElement(XmlDocument, nos.ShortName, nos.FullName, nos.SingularName, nos.PluralName); NofMetaModel.AppendNofTitle(element, nakedObjectAdapter.TitleString()); Log.Debug("objectToElement(NO): create XS element for NOF class"); XElement xsElement = Schema.CreateXsElementForNofClass(XsdDocument, element, topLevelElementWritten); // hack: every element in the XSD schema apart from first needs minimum cardinality setting. topLevelElementWritten = true; var place = new Place(nakedObjectAdapter, element); NofMetaModel.SetAttributesForClass(element, OidOrHashCode(nakedObjectAdapter)); IAssociationSpec[] fields = nos.Properties; Log.Debug("objectToElement(NO): processing fields"); var seenFields = new List<string>(); foreach (IAssociationSpec field in fields) { string fieldName = field.Id; Log.Debug("objectToElement(NO): " + DoLog("field", fieldName)); // Skip field if we have seen the name already // This is a workaround for getLastActivity(). This method exists // in AbstractNakedObject, but is not (at some level) being picked up // by the dot-net reflector as a property. On the other hand it does // exist as a field in the meta model (NakedObjectSpecification). // // Now, to re-expose the lastactivity field for .Net, a deriveLastActivity() // has been added to BusinessObject. This caused another field ofthe // same name, ultimately breaking the XSD. if (seenFields.Contains(fieldName)) { Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " SKIPPED"); continue; } seenFields.Add(fieldName); XNamespace ns = Schema.GetUri(); var xmlFieldElement = new XElement(ns + fieldName); XElement xsdFieldElement; var oneToOneAssociation = field as IOneToOneAssociationSpec; var oneToManyAssociation = field as IOneToManyAssociationSpec; if (field.ReturnSpec.IsParseable && oneToOneAssociation != null) { Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " is value"); IObjectSpec fieldNos = field.ReturnSpec; // skip fields of type XmlValue if (fieldNos != null && fieldNos.FullName != null && fieldNos.FullName.EndsWith("XmlValue")) { continue; } XElement xmlValueElement = xmlFieldElement; // more meaningful locally scoped name try { INakedObjectAdapter value = oneToOneAssociation.GetNakedObject(nakedObjectAdapter); // a null value would be a programming error, but we protect // against it anyway if (value == null) { continue; } ITypeSpec valueNos = value.Spec; // XML NofMetaModel.SetAttributesForValue(xmlValueElement, valueNos.ShortName); bool notEmpty = (value.TitleString().Length > 0); if (notEmpty) { string valueStr = value.TitleString(); xmlValueElement.Add(new XText(valueStr)); } else { NofMetaModel.SetIsEmptyAttribute(xmlValueElement, true); } } catch (Exception) { Log.Warn("objectToElement(NO): " + DoLog("field", fieldName) + ": getField() threw exception - skipping XML generation"); } // XSD xsdFieldElement = Schema.CreateXsElementForNofValue(xsElement, xmlValueElement); } else if (oneToOneAssociation != null) { Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " is IOneToOneAssociation"); XElement xmlReferenceElement = xmlFieldElement; // more meaningful locally scoped name try { INakedObjectAdapter referencedNakedObjectAdapter = oneToOneAssociation.GetNakedObject(nakedObjectAdapter); string fullyQualifiedClassName = field.ReturnSpec.FullName; // XML NofMetaModel.SetAttributesForReference(xmlReferenceElement, Schema.Prefix, fullyQualifiedClassName); if (referencedNakedObjectAdapter != null) { NofMetaModel.AppendNofTitle(xmlReferenceElement, referencedNakedObjectAdapter.TitleString()); } else { NofMetaModel.SetIsEmptyAttribute(xmlReferenceElement, true); } } catch (Exception) { Log.Warn("objectToElement(NO): " + DoLog("field", fieldName) + ": getAssociation() threw exception - skipping XML generation"); } // XSD xsdFieldElement = Schema.CreateXsElementForNofReference(xsElement, xmlReferenceElement, oneToOneAssociation.ReturnSpec.FullName); } else if (oneToManyAssociation != null) { Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " is IOneToManyAssociation"); XElement xmlCollectionElement = xmlFieldElement; // more meaningful locally scoped name try { INakedObjectAdapter collection = oneToManyAssociation.GetNakedObject(nakedObjectAdapter); ITypeOfFacet facet = collection.GetTypeOfFacetFromSpec(); IObjectSpecImmutable referencedTypeNos = facet.GetValueSpec(collection, metamodelManager.Metamodel); string fullyQualifiedClassName = referencedTypeNos.FullName; // XML NofMetaModel.SetNofCollection(xmlCollectionElement, Schema.Prefix, fullyQualifiedClassName, collection, nakedObjectManager); } catch (Exception) { Log.Warn("objectToElement(NO): " + DoLog("field", fieldName) + ": get(obj) threw exception - skipping XML generation"); } // XSD xsdFieldElement = Schema.CreateXsElementForNofCollection(xsElement, xmlCollectionElement, oneToManyAssociation.ReturnSpec.FullName); } else { Log.Info("objectToElement(NO): " + DoLog("field", fieldName) + " is unknown type; ignored"); continue; } if (xsdFieldElement != null) { xmlFieldElement.AddAnnotation(xsdFieldElement); } // XML Log.Debug("objectToElement(NO): invoking mergeTree for field"); MergeTree(element, xmlFieldElement); // XSD if (xsdFieldElement != null) { Log.Debug("objectToElement(NO): adding XS element for field to schema"); Schema.AddFieldXsElement(xsElement, xsdFieldElement); } } return place; }
/// Accept deleted paragraphs. /// /// Group together all paragraphs that contain w:p/w:pPr/w:rPr/w:del elements. Make a /// second group for the content element immediately following a paragraph that contains /// a w:del element. The code uses the approach of dealing with paragraph content at /// 'levels', ignoring paragraph content at other levels. Form a new paragraph that /// contains the content of the grouped paragraphs with deleted paragraph marks, and the /// content of the paragraph immediately following a paragraph that contains a deleted /// paragraph mark. Include in the new paragraph the paragraph properties from the /// paragraph following. When assembling the new paragraph, use a transform that collapses /// the paragraph nodes when adding content, thereby preserving custom XML and content /// controls. private static void AnnotateBlockContentElements(XElement contentContainer) { // For convenience, there is a ParagraphInfo annotation on the contentContainer. // It contains the same information as the ParagraphInfo annotation on the first // paragraph. if (contentContainer.Annotation<BlockContentInfo>() != null) return; XElement firstContentElement = contentContainer .Elements() .DescendantsAndSelf() .FirstOrDefault(e => e.Name == W.p || e.Name == W.tbl); // Add the annotation on the contentContainer. BlockContentInfo currentContentInfo = new BlockContentInfo() { PreviousBlockContentElement = null, ThisBlockContentElement = firstContentElement, NextBlockContentElement = null }; // Add as annotation even though NextParagraph is not set yet. contentContainer.AddAnnotation(currentContentInfo); while (true) { currentContentInfo.ThisBlockContentElement.AddAnnotation(currentContentInfo); // Find next sibling content element. XElement nextContentElement = null; XElement current = currentContentInfo.ThisBlockContentElement; while (true) { nextContentElement = current .ElementsAfterSelf() .DescendantsAndSelf() .FirstOrDefault(e => e.Name == W.p || e.Name == W.tbl); if (nextContentElement != null) { currentContentInfo.NextBlockContentElement = nextContentElement; break; } current = current.Parent; // When we've backed up the tree to the contentContainer, we're done. if (current == contentContainer) return; } currentContentInfo = new BlockContentInfo() { PreviousBlockContentElement = currentContentInfo.ThisBlockContentElement, ThisBlockContentElement = nextContentElement, NextBlockContentElement = null }; } }
// Creates an <xs:element> element defining the presence of the named element // representing a class public XElement CreateXsElementForNofClass(XDocument xsdDoc, XElement element, bool addCardinality) { // gather details from XML element string localName = element.Name.LocalName; // <xs:element name="AO11ConfirmAnimalRegistration"> // <xs:complexType> // <xs:sequence> // <xs:element ref="nof:title"/> // <!-- placeholder --> // </xs:sequence> // <xs:attribute ref="nof:feature" // default="class"/> // <xs:attribute ref="nof:oid"/> // <xs:attribute ref="nof:annotation"/> // <xs:attribute ref="nof:fqn"/> // </xs:complexType> // </xs:element> // xs:element/@name="class name" // add to XML schema as a global attribute XElement xsElementForNofClassElement = XsMetaModel.CreateXsElementElement(xsdDoc, localName, addCardinality); // xs:element/xs:complexType // xs:element/xs:complexType/xs:sequence XElement xsComplexTypeElement = XsMetaModel.ComplexTypeFor(xsElementForNofClassElement); XElement xsSequenceElement = XsMetaModel.SequenceFor(xsComplexTypeElement); // xs:element/xs:complexType/xs:sequence/xs:element ref="nof:title" XElement xsTitleElement = XsMetaModel.CreateXsElement(Helper.DocFor(xsSequenceElement), "element"); xsTitleElement.SetAttributeValue("ref", NofMetaModel.NofMetamodelNsPrefix + ":" + "title"); xsSequenceElement.Add(xsTitleElement); XsMetaModel.SetXsCardinality(xsTitleElement, 0, 1); // xs:element/xs:complexType/xs:sequence/xs:element ref="extensions" //addXsElementForAppExtensions(xsSequenceElement, extensions); // xs:element/xs:complexType/xs:attribute ... XsMetaModel.AddXsNofFeatureAttributeElements(xsComplexTypeElement, "class"); XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "oid"); XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "fqn"); XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "singular"); XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "plural"); XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "annotation"); element.AddAnnotation(xsElementForNofClassElement); return xsElementForNofClassElement; }
private Location GetIncludeElementLocation(XElement includeElement, ref string currentXmlFilePath, ref CSharpSyntaxNode originatingSyntax) { Location location = includeElement.Annotation<Location>(); if (location != null) { return location; } // If we are not in an XML file, then we must be in a source file. Since we're traversing the XML tree in the same // order as the DocumentationCommentWalker, we can access the elements of includeElementNodes in order. if (currentXmlFilePath == null) { Debug.Assert(nextSourceIncludeElementIndex < sourceIncludeElementNodes.Length); Debug.Assert(originatingSyntax == null); originatingSyntax = sourceIncludeElementNodes[nextSourceIncludeElementIndex]; location = originatingSyntax.Location; nextSourceIncludeElementIndex++; // #line shall not affect the base path: currentXmlFilePath = location.GetLineSpan().Path; } else { location = XmlLocation.Create(includeElement, currentXmlFilePath); } Debug.Assert(location != null); includeElement.AddAnnotation(location); return location; }
static void ApplyAnnotationToElement(XElement element, XElement annotation, object obj) { Contract.Requires<ArgumentNullException>(element != null); Contract.Requires<ArgumentNullException>(annotation != null); Contract.Requires<ArgumentNullException>(obj != null); element.AddAnnotation(obj); }
private static object ProcessBookmarkStart(XElement element) { var name = (string) element.Attribute(W.name); if (name == null) return null; var style = new Dictionary<string, string>(); var a = new XElement(Xhtml.a, new XAttribute("id", name), new XText("")); style.Add("text-decoration", "none"); a.AddAnnotation(style); return a; }
private static object ProcessBreak(XElement element) { XElement span = null; var tabWidth = (decimal?) element.Attribute(PtOpenXml.TabWidth); if (tabWidth != null) { span = new XElement(Xhtml.span); span.AddAnnotation(new Dictionary<string, string> { { "margin", string.Format(NumberFormatInfo.InvariantInfo, "0 0 0 {0:0.00}in", tabWidth) }, { "padding", "0 0 0 0" } }); } var paragraph = element.Ancestors(W.p).FirstOrDefault(); var isBidi = paragraph != null && paragraph.Elements(W.pPr).Elements(W.bidi).Any(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true); var zeroWidthChar = isBidi ? new XEntity("#x200f") : new XEntity("#x200e"); return new object[] { new XElement(Xhtml.br), zeroWidthChar, span, }; }
/* * Handle: * - b * - bdr * - caps * - color * - dstrike * - highlight * - i * - position * - rFonts * - shd * - smallCaps * - spacing * - strike * - sz * - u * - vanish * - vertAlign * * Don't handle: * - em * - emboss * - fitText * - imprint * - kern * - outline * - shadow * - w * */ private static object ConvertRun(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement run) { var style = new Dictionary<string, string>(); var sn = (string)run.Attribute(PtOpenXml.StyleName); if (sn != null) style.Add("PtStyleName", sn); var rPr = run.Element(W.rPr); if (rPr == null) { object content2 = run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m)); return content2; } // hide all content that contains the w:rPr/w:webHidden element if (rPr.Element(W.webHidden) != null) return null; // W.bdr if (rPr.Element(W.bdr) != null && (string)rPr.Elements(W.bdr).Attributes(W.val).FirstOrDefault() != "none") { style.AddIfMissing("border", "solid windowtext 1.0pt"); style.AddIfMissing("padding", "0in"); } // W.color string color = (string)rPr.Elements(W.color).Attributes(W.val).FirstOrDefault(); if (color != null) CreateColorProperty("color", color, style); // W.highlight string highlight = (string)rPr.Elements(W.highlight).Attributes(W.val).FirstOrDefault(); if (highlight != null) CreateColorProperty("background", highlight, style); // W.shd string shade = (string)rPr.Elements(W.shd).Attributes(W.fill).FirstOrDefault(); if (shade != null) CreateColorProperty("background", shade, style); // Pt.FontName string font = null; if (run.Element(W.sym) != null) font = (string)run.Elements(W.sym).Attributes(W.font).FirstOrDefault(); else font = (string)run.Attributes(PtOpenXml.FontName).FirstOrDefault(); if (font != null) CreateFontCssProperty(font, style); // W.sz var languageType = (string)run.Attribute(PtOpenXml.LanguageType); decimal? sz = null; if (languageType == "bidi") sz = (decimal?)rPr.Elements(W.szCs).Attributes(W.val).FirstOrDefault(); else sz = (decimal?)rPr.Elements(W.sz).Attributes(W.val).FirstOrDefault(); if (sz != null) style.AddIfMissing("font-size", string.Format("{0}pt", sz / 2.0m)); // W.caps if (getBoolProp(rPr, W.caps)) style.AddIfMissing("text-transform", "uppercase"); // W.smallCaps if (getBoolProp(rPr, W.smallCaps)) style.AddIfMissing("font-variant", "small-caps"); // W.spacing decimal? spacingInTwips = (decimal?)rPr.Elements(W.spacing).Attributes(W.val).FirstOrDefault(); if (spacingInTwips != null) style.AddIfMissing("letter-spacing", string.Format("{0}pt", spacingInTwips / 20)); // W.position decimal? position = (decimal?)rPr.Elements(W.position).Attributes(W.val).FirstOrDefault(); if (position != null) { style.AddIfMissing("position", "relative"); style.AddIfMissing("top", string.Format("{0}pt", -(position / 2))); } // W.vanish if (getBoolProp(rPr, W.vanish)) style.AddIfMissing("display", "none"); object content = run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m)); // W.u if (rPr.Element(W.u) != null && (string)rPr.Elements(W.u).Attributes(W.val).FirstOrDefault() != "none") { var newContent = new XElement(Xhtml.u, content); if (newContent.Nodes().Any()) content = newContent; style.AddIfMissing("text-decoration", "underline"); } // W.i if (getBoolProp(rPr, W.i)) { var newContent = new XElement(Xhtml.i, content); if (newContent.Nodes().Any()) content = newContent; style.AddIfMissing("font-style", "italic"); } // W.b if (getBoolProp(rPr, W.b)) { var newContent = new XElement(Xhtml.b, content); if (newContent.Nodes().Any()) content = newContent; style.AddIfMissing("font-weight", "bold"); } else { style.AddIfMissing("font-weight", "normal"); } // W.strike if (getBoolProp(rPr, W.strike) || getBoolProp(rPr, W.dstrike)) { var newContent = new XElement(Xhtml.s, content); if (newContent.Nodes().Any()) content = newContent; style.AddIfMissing("text-decoration", "line-through"); } // W.vertAlign if (rPr.Element(W.vertAlign) != null && (string)rPr.Elements(W.vertAlign).Attributes(W.val).FirstOrDefault() == "superscript") { var newContent = new XElement(Xhtml.sup, content); if (newContent.Nodes().Any()) content = newContent; } if (rPr.Element(W.vertAlign) != null && (string)rPr.Elements(W.vertAlign).Attributes(W.val).FirstOrDefault() == "subscript") { var newContent = new XElement(Xhtml.sub, content); if (newContent.Nodes().Any()) content = newContent; } var rtl = rPr.Element(W.rtl); var isRtl = rtl != null; var paragraph = run.Ancestors(W.p).FirstOrDefault(); var paraBidi = paragraph .Elements(W.pPr) .Elements(W.bidi) .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true) .FirstOrDefault(); var paraIsBidi = paraBidi != null; string lang = null; if (languageType == "western") lang = (string)rPr.Elements(W.lang).Attributes(W.val).FirstOrDefault(); else if (languageType == "bidi") lang = (string)rPr.Elements(W.lang).Attributes(W.bidi).FirstOrDefault(); else if (languageType == "eastAsia") lang = (string)rPr.Elements(W.lang).Attributes(W.eastAsia).FirstOrDefault(); // only do the following for text runs. XEntity runStartMark = null; XEntity runEndMark = null; // Can't add directional marks if the font-family is symbol - they are visible, and display as a ? bool addDirectionalMarks = true; if (style.ContainsKey("font-family")) { if (style["font-family"].ToLower() == "symbol") addDirectionalMarks = false; } if (addDirectionalMarks) { if (run.Element(W.t) != null) { if (isRtl) { runStartMark = new XEntity("#x200f"); // RLM runEndMark = new XEntity("#x200f"); // RLM } else { if (paraIsBidi) { runStartMark = new XEntity("#x200e"); // LRM runEndMark = new XEntity("#x200e"); // LRM } } } } string defaultLanguage = "en-US"; // todo need to get defaultLanguage if (lang == null) lang = defaultLanguage; XAttribute langAttribute = new XAttribute("lang", lang); if (lang == defaultLanguage) langAttribute = null; if (style.Any() || isRtl || langAttribute != null) { style.AddIfMissing("margin", "0in"); style.AddIfMissing("padding", "0in"); var xe = new XElement(Xhtml.span, langAttribute, runStartMark, content, runEndMark); xe.AddAnnotation(style); content = xe; } return content; }
private static object ProcessTableCell(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element) { var style = new Dictionary<string, string>(); XAttribute colSpan = null; XAttribute rowSpan = null; var tcPr = element.Element(W.tcPr); if (tcPr != null) { if ((string) tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart") { var currentRow = element.Parent.ElementsBeforeSelf(W.tr).Count(); var currentCell = element.ElementsBeforeSelf(W.tc).Count(); var tbl = element.Parent.Parent; int rowSpanCount = 1; currentRow += 1; while (true) { var row = tbl.Elements(W.tr).Skip(currentRow).FirstOrDefault(); if (row == null) break; var cell2 = row.Elements(W.tc).Skip(currentCell).FirstOrDefault(); if (cell2 == null) break; if (cell2.Elements(W.tcPr).Elements(W.vMerge).FirstOrDefault() == null) break; if ((string) cell2.Elements(W.tcPr).Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart") break; currentRow += 1; rowSpanCount += 1; } rowSpan = new XAttribute("rowspan", rowSpanCount); } if (tcPr.Element(W.vMerge) != null && (string) tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() != "restart") return null; if (tcPr.Element(W.vAlign) != null) { var vAlignVal = (string) tcPr.Elements(W.vAlign).Attributes(W.val).FirstOrDefault(); if (vAlignVal == "top") style.AddIfMissing("vertical-align", "top"); else if (vAlignVal == "center") style.AddIfMissing("vertical-align", "middle"); else if (vAlignVal == "bottom") style.AddIfMissing("vertical-align", "bottom"); else style.AddIfMissing("vertical-align", "middle"); } style.AddIfMissing("vertical-align", "top"); if ((string) tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "dxa") { decimal width = (int) tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault(); style.AddIfMissing("width", string.Format(NumberFormatInfo.InvariantInfo, "{0}pt", width/20m)); } if ((string) tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "pct") { decimal width = (int) tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault(); style.AddIfMissing("width", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.0}%", width/50m)); } var tcBorders = tcPr.Element(W.tcBorders); GenerateBorderStyle(tcBorders, W.top, style, BorderType.Cell); GenerateBorderStyle(tcBorders, W.right, style, BorderType.Cell); GenerateBorderStyle(tcBorders, W.bottom, style, BorderType.Cell); GenerateBorderStyle(tcBorders, W.left, style, BorderType.Cell); CreateStyleFromShd(style, tcPr.Element(W.shd)); var gridSpan = tcPr.Elements(W.gridSpan).Attributes(W.val).Select(a => (int?) a).FirstOrDefault(); if (gridSpan != null) colSpan = new XAttribute("colspan", (int) gridSpan); } style.AddIfMissing("padding-top", "0"); style.AddIfMissing("padding-bottom", "0"); var cell = new XElement(Xhtml.td, rowSpan, colSpan, CreateBorderDivs(wordDoc, settings, element.Elements())); cell.AddAnnotation(style); return cell; }
private static object ConvertToHtmlTransform(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XNode node, bool suppressTrailingWhiteSpace, decimal currentMarginLeft) { XElement element = node as XElement; if (element != null) { if (element.Name == W.document) return new XElement(Xhtml.html, new XElement(Xhtml.head, new XElement(Xhtml.meta, new XAttribute("http-equiv", "Content-Type"), new XAttribute("content", "text/html; charset=utf-8")), new XElement(Xhtml.meta, new XAttribute("name", "Generator"), new XAttribute("content", "PowerTools for Open XML")), settings.PageTitle != null ? new XElement(Xhtml.title, new XText(settings.PageTitle)) : null ), element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)) ); // Transform the w:body element to the XHTML h:body element. if (element.Name == W.body) { var sectionDivContent = new XElement(Xhtml.body, CreateSectionDivs(wordDoc, settings, element)); return sectionDivContent; } if (element.Name == W.p) { var bidi = element .Elements(W.pPr) .Elements(W.bidi) .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true) .FirstOrDefault(); var isBidi = bidi != null; string styleId = (string)element.Elements(W.pPr).Elements(W.pStyle) .Attributes(W.val).FirstOrDefault(); if (styleId != null) { XElement style = wordDoc.MainDocumentPart.StyleDefinitionsPart .GetXDocument().Root.Elements(W.style) .Where(s => (string)s.Attribute(W.styleId) == styleId) .FirstOrDefault(); if (style != null) { int? outlineLevel = (int?)style.Elements(W.pPr) .Elements(W.outlineLvl).Attributes(W.val).FirstOrDefault(); if (outlineLevel != null && outlineLevel <= 5) { XName elementName = Xhtml.xhtml + string.Format("h{0}", outlineLevel + 1); return ConvertParagraph(wordDoc, settings, element, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi); } else { XName elementName = Xhtml.p; var o = ConvertParagraph(wordDoc, settings, element, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi); return o; } } } else { XName elementName = Xhtml.p; var o = ConvertParagraph(wordDoc, settings, element, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi); return o; } } // Transform hyperlinks to the XHTML h:A element. if (element.Name == W.hyperlink && element.Attribute(R.id) != null) { try { return new XElement(Xhtml.A, new XAttribute("href", wordDoc.MainDocumentPart .HyperlinkRelationships .Where(x => x.Id == (string)element.Attribute(R.id)) .First() .Uri ), element.Elements(W.r).Select(run => ConvertRun(wordDoc, settings, run)) ); } catch (UriFormatException) { return element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)); } } // Transform hyperlinks to bookmarks to the XHTML h:A element. if (element.Name == W.hyperlink && element.Attribute(W.anchor) != null) { var style = new Dictionary<string, string>(); var a = new XElement(Xhtml.A, new XAttribute("href", "#" + (string)element.Attribute(W.anchor)), element .Elements(W.r) .Select(run => ConvertRun(wordDoc, settings, run))); style.Add("text-decoration", "none"); a.AddAnnotation(style); return a; } // Transform contents of runs. if (element.Name == W.r) return ConvertRun(wordDoc, settings, element); // Transform w:bookmarkStart into anchor if (element.Name == W.bookmarkStart) { var name = (string)element.Attribute(W.name); if (name != null) { var style = new Dictionary<string, string>(); var a = new XElement(Xhtml.A, new XAttribute("id", name), new XText("")); style.Add("text-decoration", "none"); a.AddAnnotation(style); return a; } } // Transform every w:t element to a text node. if (element.Name == W.t) { var textWithEntities = ConvertEntities(element.Value); return textWithEntities; } // Transform symbols to spans if (element.Name == W.sym) { var cs = (string)element.Attribute(W._char); var c = Convert.ToInt32(cs, 16); var symbolSpan = new XElement(Xhtml.span, new XEntity(string.Format("#{0}", ((int)c).ToString()))); return symbolSpan; } // Transform tabs that have the pt:TabWidth attribute set if (element.Name == W.tab) { var tabWidthAtt = element.Attribute(PtOpenXml.TabWidth); if (tabWidthAtt != null) { var leader = (string)element.Attribute(PtOpenXml.Leader); var tabWidth = (decimal)tabWidthAtt; var style = new Dictionary<string, string>(); XElement span; if (leader != null) { var leaderChar = "."; if (leader == "hyphen") leaderChar = "-"; else if (leader == "dot") leaderChar = "."; else if (leader == "underscore") leaderChar = "_"; var runContainingTabToReplace = element.Ancestors(W.r).First(); var fontNameAtt = runContainingTabToReplace.Attribute(PtOpenXml.pt + "FontName"); if (fontNameAtt == null) fontNameAtt = runContainingTabToReplace.Ancestors(W.p).First() .Attribute(PtOpenXml.pt + "FontName"); var dummyRun = new XElement(W.r, fontNameAtt, runContainingTabToReplace.Elements(W.rPr), new XElement(W.t, leaderChar)); var widthOfLeaderChar = CalcWidthOfRunInTwips(dummyRun); bool forceArial = false; if (widthOfLeaderChar == 0) { dummyRun = new XElement(W.r, new XAttribute(PtOpenXml.FontName, "Arial"), runContainingTabToReplace.Elements(W.rPr), new XElement(W.t, leaderChar)); widthOfLeaderChar = CalcWidthOfRunInTwips(dummyRun); forceArial = true; } if (widthOfLeaderChar != 0) { var numberOfLeaderChars = (int)(Math.Floor((tabWidth * 1440) / widthOfLeaderChar)); if (numberOfLeaderChars < 0) numberOfLeaderChars = 0; span = new XElement(Xhtml.span, " " + "".PadRight(numberOfLeaderChars, leaderChar[0]) + " "); style.Add("margin", "0 0 0 0"); style.Add("padding", "0 0 0 0"); style.Add("width", string.Format("{0:0.00}in", tabWidth)); style.Add("text-align", "center"); if (forceArial) style.Add("font-family", "Arial"); } else { span = new XElement(Xhtml.span, " "); style.Add("margin", "0 0 0 0"); style.Add("padding", "0 0 0 0"); style.Add("width", string.Format("{0:0.00}in", tabWidth)); style.Add("text-align", "center"); if (leader == "underscore") { style.Add("text-decoration", "underline"); } } } else { #if false var bidi = element .Ancestors(W.p) .Take(1) .Elements(W.pPr) .Elements(W.bidi) .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true) .FirstOrDefault(); var isBidi = bidi != null; if (isBidi) span = new XElement(Xhtml.span, new XEntity("#x200f")); // RLM else span = new XElement(Xhtml.span, new XEntity("#x200e")); // LRM #else span = new XElement(Xhtml.span, new XEntity("nbsp")); #endif style.Add("margin", string.Format("0 0 0 {0:0.00}in", tabWidth)); style.Add("padding", "0 0 0 0"); } span.AddAnnotation(style); return span; } } // Transform w:br to h:br. if (element.Name == W.br || element.Name == W.cr) { XElement span = null; var tabWidth = (decimal?)element.Attribute(PtOpenXml.TabWidth); if (tabWidth != null) { span = new XElement(Xhtml.span); var style = new Dictionary<string, string>(); style.Add("margin", string.Format("0 0 0 {0:0.00}in", tabWidth)); style.Add("padding", "0 0 0 0"); span.AddAnnotation(style); } var paragraph = element.Ancestors(W.p).FirstOrDefault(); bool isBidi = false; if (paragraph != null) { var bidi = paragraph .Elements(W.pPr) .Elements(W.bidi) .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true) .FirstOrDefault(); isBidi = bidi != null; } var br = new XElement(Xhtml.br); XEntity zeroWidthChar = null; if (isBidi) zeroWidthChar = new XEntity("#x200f"); // RLM else zeroWidthChar = new XEntity("#x200e"); // LRM return new object[] { br, zeroWidthChar, span, }; } // Transform w:noBreakHyphen to '-' if (element.Name == W.noBreakHyphen) return new XText("-"); // Transform w:tbl to h:tbl. if (element.Name == W.tbl) { var style = new Dictionary<string, string>(); style.AddIfMissing("border-collapse", "collapse"); style.AddIfMissing("border", "none"); var bidiVisual = element.Elements(W.tblPr).Elements(W.bidiVisual).FirstOrDefault(); var tblW = element.Elements(W.tblPr).Elements(W.tblW).FirstOrDefault(); if (tblW != null) { var type = (string)tblW.Attribute(W.type); if (type != null && type == "pct") { var w = (int)tblW.Attribute(W._w); style.AddIfMissing("width", (w / 50).ToString() + "%"); } } var tblInd = element.Elements(W.tblPr).Elements(W.tblInd).FirstOrDefault(); if (tblInd != null) { var tblIndType = (string)tblInd.Attribute(W.type); if (tblIndType != null) { if (tblIndType == "dxa") { var width = (decimal?)tblInd.Attribute(W._w); if (width != null) { style.AddIfMissing("margin-left", string.Format("{0}pt", width / 20m)); } } } } XAttribute tableDirection = null; if (bidiVisual != null) { tableDirection = new XAttribute("dir", "rtl"); } else { tableDirection = new XAttribute("dir", "ltr"); } style.AddIfMissing("margin-bottom", ".001pt"); var table = new XElement(Xhtml.table, new XAttribute("border", "1"), new XAttribute("cellspacing", 0), new XAttribute("cellpadding", 0), tableDirection, element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft))); table.AddAnnotation(style); var jc = (string)element.Elements(W.tblPr).Elements(W.jc).Attributes(W.val).FirstOrDefault(); if (jc == null) jc = "left"; XAttribute dir = null; XAttribute jcToUse = null; if (bidiVisual != null) { dir = new XAttribute("dir", "rtl"); if (jc == "left") jcToUse = new XAttribute("align", "right"); else if (jc == "right") jcToUse = new XAttribute("align", "left"); else if (jc == "center") jcToUse = new XAttribute("align", "center"); } else { jcToUse = new XAttribute("align", jc); } var tableDiv = new XElement(Xhtml.div, dir, jcToUse, table); return tableDiv; } // Transform w:tr to h:tr. if (element.Name == W.tr) { var style = new Dictionary<string, string>(); int? trHeight = (int?)element.Elements(W.trPr).Elements(W.trHeight).Attributes(W.val).FirstOrDefault(); if (trHeight != null) style.AddIfMissing("height", string.Format("{0}in", (decimal)trHeight / 1440m)); var htmlRow = new XElement(Xhtml.tr, element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft))); if (style.Any()) htmlRow.AddAnnotation(style); return htmlRow; } // Transform w:tc to h:td. if (element.Name == W.tc) { var style = new Dictionary<string, string>(); XAttribute colSpan = null; XAttribute rowSpan = null; var tcPr = element.Element(W.tcPr); if (tcPr != null) { if ((string)tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart") { var currentRow = element.Parent.ElementsBeforeSelf(W.tr).Count(); var currentCell = element.ElementsBeforeSelf(W.tc).Count(); var tbl = element.Parent.Parent; int rowSpanCount = 1; currentRow += 1; while (true) { var row = tbl.Elements(W.tr).Skip(currentRow).FirstOrDefault(); if (row == null) break; var cell2 = row.Elements(W.tc).Skip(currentCell).FirstOrDefault(); if (cell2 == null) break; if (cell2.Elements(W.tcPr).Elements(W.vMerge).FirstOrDefault() == null) break; if ((string)cell2.Elements(W.tcPr).Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart") break; currentRow += 1; rowSpanCount += 1; } rowSpan = new XAttribute("rowspan", rowSpanCount); } if (tcPr.Element(W.vMerge) != null && (string)tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() != "restart") return null; if (tcPr.Element(W.vAlign) != null) { var vAlignVal = (string)tcPr.Elements(W.vAlign).Attributes(W.val).FirstOrDefault(); if (vAlignVal == "top") style.AddIfMissing("vertical-align", "top"); else if (vAlignVal == "center") style.AddIfMissing("vertical-align", "middle"); else if (vAlignVal == "bottom") style.AddIfMissing("vertical-align", "bottom"); else style.AddIfMissing("vertical-align", "middle"); } style.AddIfMissing("vertical-align", "top"); if ((string)tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "dxa") { decimal width = (int)tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault(); style.AddIfMissing("width", string.Format("{0}pt", width / 20m)); } if ((string)tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "pct") { decimal width = (int)tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault(); style.AddIfMissing("width", string.Format("{0:0.0}%", width / 50m)); } var tcBorders = tcPr.Element(W.tcBorders); GenerateBorderStyle(tcBorders, W.top, style, BorderType.Cell); GenerateBorderStyle(tcBorders, W.right, style, BorderType.Cell); GenerateBorderStyle(tcBorders, W.bottom, style, BorderType.Cell); GenerateBorderStyle(tcBorders, W.left, style, BorderType.Cell); CreateStyleFromShd(style, tcPr.Element(W.shd)); var gridSpan = (int?)tcPr.Elements(W.gridSpan).Attributes(W.val).Select(a => (int?)a).FirstOrDefault(); if (gridSpan != null) colSpan = new XAttribute("colspan", (int)gridSpan); } style.AddIfMissing("padding-top", "0in"); style.AddIfMissing("padding-bottom", "0in"); var cell = new XElement(Xhtml.td, rowSpan, colSpan, CreateBorderDivs(wordDoc, settings, element.Elements())); cell.AddAnnotation(style); return cell; } // Transform images if (element.Name == W.drawing || element.Name == W.pict || element.Name == W._object) { if (settings.ImageHandler == null) return null; return ProcessImage(wordDoc, element, settings.ImageHandler); } if (element.Name == W.sdt) { var relevantAncestors = element.Ancestors().TakeWhile(a => a.Name != W.txbxContent); var isRunLevelContentControl = relevantAncestors.Any(a => a.Name == W.p); if (isRunLevelContentControl) { var o = element.Element(W.sdtContent).Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)) .ToList(); return o; } else { var o = CreateBorderDivs(wordDoc, settings, element.Element(W.sdtContent).Elements()); return o; } } if (element.Name == W.smartTag || element.Name == W.fldSimple) { var o = CreateBorderDivs(wordDoc, settings, element.Elements()); return o; } return null; } return null; }
private static XElement CharStyleRollup(FormattingAssemblerInfo fai, WordprocessingDocument wDoc, XElement runOrPara) { var sXDoc = wDoc.MainDocumentPart.StyleDefinitionsPart.GetXDocument(); string charStyle = null; string paraStyle = null; XElement rPr = null; XElement pPr = null; XElement pStyle = null; XElement rStyle = null; CachedParaInfo cpi = null; // CachedParaInfo is an optimization for the case where a paragraph contains thousands of runs. if (runOrPara.Name == W.p) { cpi = runOrPara.Annotation<CachedParaInfo>(); if (cpi != null) pPr = cpi.ParagraphProperties; else { pPr = runOrPara.Element(W.pPr); if (pPr != null) { paraStyle = (string)pPr.Elements(W.pStyle).Attributes(W.val).FirstOrDefault(); } else { paraStyle = fai.DefaultParagraphStyleName; } cpi = new CachedParaInfo { ParagraphProperties = pPr, ParagraphStyleName = paraStyle, }; runOrPara.AddAnnotation(cpi); } if (pPr != null) { rPr = pPr.Element(W.rPr); } } else { rPr = runOrPara.Element(W.rPr); } if (rPr != null) { rStyle = rPr.Element(W.rStyle); if (rStyle != null) { charStyle = (string)rStyle.Attribute(W.val); } else { if (runOrPara.Name == W.r) charStyle = (string)runOrPara .Ancestors(W.p) .Take(1) .Elements(W.pPr) .Elements(W.pStyle) .Attributes(W.val) .FirstOrDefault(); else charStyle = (string)runOrPara .Elements(W.pPr) .Elements(W.pStyle) .Attributes(W.val) .FirstOrDefault(); } } if (charStyle == null) { if (runOrPara.Name == W.r) { var ancestorPara = runOrPara.Ancestors(W.p).First(); cpi = ancestorPara.Annotation<CachedParaInfo>(); if (cpi != null) charStyle = cpi.ParagraphStyleName; else charStyle = (string)runOrPara.Ancestors(W.p).First().Elements(W.pPr).Elements(W.pStyle).Attributes(W.val).FirstOrDefault(); } if (charStyle == null) { charStyle = fai.DefaultParagraphStyleName; } } // A run always must have an ancestor paragraph. XElement para = null; var rolledUpParaStyleRunProps = new XElement(W.rPr); if (runOrPara.Name == W.r) { para = runOrPara.Ancestors(W.p).FirstOrDefault(); } else { para = runOrPara; } cpi = para.Annotation<CachedParaInfo>(); if (cpi != null) { pPr = cpi.ParagraphProperties; } else { pPr = para.Element(W.pPr); } if (pPr != null) { pStyle = pPr.Element(W.pStyle); if (pStyle != null) { paraStyle = (string)pStyle.Attribute(W.val); } else { paraStyle = fai.DefaultParagraphStyleName; } } else paraStyle = fai.DefaultParagraphStyleName; string key = (paraStyle == null ? "[null]" : paraStyle) + "~|~" + (charStyle == null ? "[null]" : charStyle); XElement rolledRunProps = null; if (fai.RolledCharacterStyles.ContainsKey(key)) rolledRunProps = fai.RolledCharacterStyles[key]; else { XElement rolledUpCharStyleRunProps = new XElement(W.rPr); if (charStyle != null) { rolledUpCharStyleRunProps = CharStyleStack(wDoc, charStyle) .Aggregate(new XElement(W.rPr), (r, s) => { var newRunProps = MergeStyleElement(s, r); return newRunProps; }); } if (paraStyle != null) { rolledUpParaStyleRunProps = ParaStyleRunPropsStack(wDoc, paraStyle) .Aggregate(new XElement(W.rPr), (r, s) => { var newCharStyleRunProps = MergeStyleElement(s, r); return newCharStyleRunProps; }); } rolledRunProps = MergeStyleElement(rolledUpCharStyleRunProps, rolledUpParaStyleRunProps); fai.RolledCharacterStyles.Add(key, rolledRunProps); } return rolledRunProps; }
/// <summary> /// Validate the behavior of annotations on Container. /// </summary> /// <param name="contextValue"></param> /// <returns></returns> //[Variation(Desc = "ContainerAnnotations")] public void ContainerAnnotations() { XElement element1 = new XElement("e1"); XElement element2 = new XElement("e2"); // Check argument null exception on add. try { element1.AddAnnotation(null); Validate.ExpectedThrow(typeof(ArgumentNullException)); } catch (Exception ex) { Validate.Catch(ex, typeof(ArgumentNullException)); } // Before adding anything, should not be able to get any annotations. Validate.IsNull(element1.Annotation(typeof(object))); element1.RemoveAnnotations(typeof(object)); Validate.IsNull(element1.Annotation(typeof(object))); // First annotation: 2 cases, object[] and other. object obj1 = "hello"; element1.AddAnnotation(obj1); Validate.IsNull(element1.Annotation(typeof(byte))); Validate.IsReferenceEqual(element1.Annotation(typeof(string)), obj1); element1.RemoveAnnotations(typeof(string)); Validate.IsNull(element1.Annotation(typeof(string))); object[] obj2 = new object[] { 10, 20, 30 }; element2.AddAnnotation(obj2); Validate.IsReferenceEqual(element2.Annotation(typeof(object[])), obj2); Validate.Enumerator<object>((object[])element2.Annotation(typeof(object[])), new object[] { 10, 20, 30 }); element2.RemoveAnnotations(typeof(object[])); Validate.IsNull(element2.Annotation(typeof(object[]))); // Single annotation; add a second one. Check that duplicates are allowed. object obj3 = 10; element1.AddAnnotation(obj3); Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3); element1.AddAnnotation(1000); element1.RemoveAnnotations(typeof(int[])); Validate.IsNull(element1.Annotation(typeof(object[]))); object obj4 = "world"; element1.AddAnnotation(obj4); Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3); Validate.IsReferenceEqual(element1.Annotation(typeof(string)), obj4); // Multiple annotations already. Add one on the end. object obj5 = 20L; element1.AddAnnotation(obj5); Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3); Validate.IsReferenceEqual(element1.Annotation(typeof(string)), obj4); Validate.IsReferenceEqual(element1.Annotation(typeof(long)), obj5); // Remove one from the middle and then add, which should use the // freed slot. element1.RemoveAnnotations(typeof(string)); Validate.IsNull(element1.Annotation(typeof(string))); object obj6 = 30m; element1.AddAnnotation(obj6); Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3); Validate.IsReferenceEqual(element1.Annotation(typeof(long)), obj5); Validate.IsReferenceEqual(element1.Annotation(typeof(decimal)), obj6); // Ensure that duplicates are allowed. element1.AddAnnotation(40m); Validate.IsNull(element1.Annotation(typeof(sbyte))); // A couple of additional remove cases. element2.AddAnnotation(obj2); element2.AddAnnotation(obj3); element2.AddAnnotation(obj5); element2.AddAnnotation(obj6); element2.RemoveAnnotations(typeof(float)); Validate.IsNull(element2.Annotation(typeof(float))); }
private static object CreateBorderDivs(WordprocessingDocument wordDoc, HtmlConverterSettings settings, IEnumerable<XElement> elements) { return elements.GroupAdjacent(e => { if (e.Elements(W.pPr).Elements(W.pBdr).Any()) { var pBdr = e.Element(W.pPr).Element(W.pBdr); var indStr = ""; var ind = e.Element(W.pPr).Element(W.ind); if (ind != null) indStr = ind.ToString(SaveOptions.DisableFormatting); return pBdr.ToString(SaveOptions.DisableFormatting) + indStr; } else if (e.Name == W.tbl) { return "table"; } else { return ""; // empty string means no pBdr } }) .Select(g => { if (g.Key == "") { var o = GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, 0m); return (object)o; } if (g.Key == "table") { var o = g.Select(gc => ConvertToHtmlTransform(wordDoc, settings, gc, false, 0)); return o; } var pPr = g.First().Element(W.pPr); var pBdr = pPr.Element(W.pBdr); Dictionary<string, string> style = new Dictionary<string, string>(); GenerateBorderStyle(pBdr, W.top, style, BorderType.Paragraph); GenerateBorderStyle(pBdr, W.right, style, BorderType.Paragraph); GenerateBorderStyle(pBdr, W.bottom, style, BorderType.Paragraph); GenerateBorderStyle(pBdr, W.left, style, BorderType.Paragraph); var ind = pPr.Element(W.ind); decimal currentMarginLeft = 0m; if (ind != null) { decimal? left = (decimal?)ind.Attribute(W.left); decimal leftInInches = 0; if (left != null) leftInInches = (decimal)left / 1440; decimal? hanging = (decimal?)ind.Attribute(W.hanging); decimal hangingInInches = 0; if (hanging != null) hangingInInches = -(decimal)hanging / 1440; currentMarginLeft = leftInInches + hangingInInches; style.AddIfMissing("margin-left", string.Format("{0:0.00}in", currentMarginLeft)); } var div = new XElement(Xhtml.div, GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, currentMarginLeft)); div.AddAnnotation(style); return div; }) .ToList(); }
/* * Notes on line spacing * * the w:line and w:lineRule attributes control spacing between lines - including between lines within a paragraph * * If w:spacing w:lineRule="auto" then * w:spacing w:line is a percentage where 240 == 100% * * (line value / 240) * 100 = percentage of line * * If w:spacing w:lineRule="exact" or w:lineRule="atLeast" then * w:spacing w:line is in twips * 1440 = exactly one inch from line to line * * Handle * - ind * - jc * - numPr * - pBdr * - shd * - spacing * - textAlignment * * Don't Handle (yet) * - adjustRightInd? * - autoSpaceDE * - autoSpaceDN * - bidi * - contextualSpacing * - divId * - framePr * - keepLines * - keepNext * - kinsoku * - mirrorIndents * - overflowPunct * - pageBreakBefore * - snapToGrid * - suppressAutoHyphens * - suppressLineNumbers * - suppressOverlap * - tabs * - textBoxTightWrap * - textDirection * - topLinePunct * - widowControl * - wordWrap * */ private static object ConvertParagraph(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement paragraph, XName elementName, bool suppressTrailingWhiteSpace, decimal currentMarginLeft, bool isBidi) { var style = DefineParagraphStyle(paragraph, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi); var rtl = isBidi ? new XAttribute("dir", "rtl") : new XAttribute("dir", "ltr"); var firstMark = isBidi ? new XEntity("#x200f") : null; // Analyze initial runs to see whether we have a tab, in which case we will render // a span with a defined width and ignore the tab rather than rendering the text // preceding the tab and the tab as a span with a computed width. var firstTabRun = paragraph .Elements(W.r) .FirstOrDefault(run => run.Elements(W.tab).Any()); var elementsPrecedingTab = firstTabRun != null ? paragraph.Elements(W.r).TakeWhile(e => e != firstTabRun) .Where(e => e.Elements().Any(c => c.Attributes(PtOpenXml.TabWidth).Any())).ToList() : Enumerable.Empty<XElement>().ToList(); // TODO: Revisit // For the time being, if a hyperlink field precedes the tab, we'll render it as before. var hyperlinkPrecedesTab = elementsPrecedingTab .Elements(W.r) .Elements(W.instrText) .Select(e => e.Value) .Any(value => value != null && value.TrimStart().ToUpper().StartsWith("HYPERLINK")); if (hyperlinkPrecedesTab) { var paraElement1 = new XElement(elementName, rtl, firstMark, ConvertContentThatCanContainFields(wordDoc, settings, paragraph.Elements())); paraElement1.AddAnnotation(style); return paraElement1; } var txElementsPrecedingTab = TransformElementsPrecedingTab(wordDoc, settings, elementsPrecedingTab, firstTabRun); var elementsSucceedingTab = firstTabRun != null ? paragraph.Elements().SkipWhile(e => e != firstTabRun).Skip(1) : paragraph.Elements(); var paraElement = new XElement(elementName, rtl, firstMark, txElementsPrecedingTab, ConvertContentThatCanContainFields(wordDoc, settings, elementsSucceedingTab)); paraElement.AddAnnotation(style); return paraElement; }
/* * Notes on line spacing * * the w:line and w:lineRule attributes control spacing between lines - including between lines within a paragraph * * If w:spacing w:lineRule="auto" then * w:spacing w:line is a percentage where 240 == 100% * * (line value / 240) * 100 = percentage of line * * If w:spacing w:lineRule="exact" or w:lineRule="atLeast" then * w:spacing w:line is in twips * 1440 = exactly one inch from line to line * * Handle * - ind * - jc * - numPr * - pBdr * - shd * - spacing * - textAlignment * * Don't Handle (yet) * - adjustRightInd? * - autoSpaceDE * - autoSpaceDN * - bidi * - contextualSpacing * - divId * - framePr * - keepLines * - keepNext * - kinsoku * - mirrorIndents * - overflowPunct * - pageBreakBefore * - snapToGrid * - suppressAutoHyphens * - suppressLineNumbers * - suppressOverlap * - tabs * - textBoxTightWrap * - textDirection * - topLinePunct * - widowControl * - wordWrap * */ private static object ConvertParagraph(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement paragraph, XName elementName, bool suppressTrailingWhiteSpace, decimal currentMarginLeft, bool isBidi) { var style = new Dictionary<string, string>(); var sn = (string)paragraph.Attribute(PtOpenXml.StyleName); if (sn != null) style.Add("PtStyleName", sn); XElement pPr = paragraph.Element(W.pPr); if (pPr != null) { var spacing = pPr.Element(W.spacing); if (spacing != null) { var spacingBefore = (decimal?)spacing.Attribute(W.before); if (spacingBefore != null) style.AddIfMissing("margin-top", string.Format("{0}pt", spacingBefore / 20.0m)); var lineRule = (string)spacing.Attribute(W.lineRule); if (lineRule == "auto") { var line = (decimal)spacing.Attribute(W.line); if (line != 240m) { var pct = (line / 240m) * 100m; style.Add("line-height", string.Format("{0:0.0}%", pct)); } } if (lineRule == "exact") { var line = (decimal)spacing.Attribute(W.line); var points = line / 20m; style.Add("line-height", string.Format("{0:0.0}pt", points)); } if (lineRule == "atLeast") { var line = (decimal)spacing.Attribute(W.line); var points = line / 20m; if (points >= 14m) style.Add("line-height", string.Format("{0:0.0}pt", points)); } decimal? spacingAfter; if (suppressTrailingWhiteSpace) spacingAfter = 0; else spacingAfter = (decimal?)spacing.Attribute(W.after) /*+ addToSpacing*/; if (spacingAfter != null) style.AddIfMissing("margin-bottom", string.Format("{0}pt", spacingAfter / 20.0m)); } var ind = pPr.Element(W.ind); if (ind != null) { decimal? left = (decimal?)ind.Attribute(W.left); if (left != null) { decimal leftInInches = (decimal)left / 1440 - currentMarginLeft; style.AddIfMissing(isBidi ? "margin-right" : "margin-left", string.Format("{0:0.00}in", leftInInches)); } decimal? right = (decimal?)ind.Attribute(W.right); if (right != null) { decimal rightInInches = (decimal)right / 1440; style.AddIfMissing(isBidi ? "margin-left" : "margin-right", string.Format("{0:0.00}in", rightInInches)); } decimal? firstLine = (decimal?)ind.Attribute(W.firstLine); if (firstLine != null) { decimal firstLineInInches = (decimal)firstLine / 1440m; style.AddIfMissing("text-indent", string.Format("{0:0.00}in", firstLineInInches)); } decimal? hanging = (decimal?)ind.Attribute(W.hanging); if (hanging != null) { decimal hangingInInches = (decimal)-hanging / 1440m; style.AddIfMissing("text-indent", string.Format("{0:0.00}in", hangingInInches)); } } // todo need to handle // - both // - mediumKashida // - distribute // - numTab // - highKashida // - lowKashida // - thaiDistribute var jcVal = (string)pPr.Elements(W.jc).Attributes(W.val).FirstOrDefault(); if (jcVal == null) { jcVal = "left"; } if (jcVal == "left") { if (isBidi) style.AddIfMissing("text-align", "right"); else style.AddIfMissing("text-align", "left"); } else if (jcVal == "right") { if (isBidi) style.AddIfMissing("text-align", "left"); else style.AddIfMissing("text-align", "right"); } else if (jcVal == "center") style.AddIfMissing("text-align", "center"); else if (jcVal == "both") style.AddIfMissing("text-align", "justify"); CreateStyleFromShd(style, pPr.Element(W.shd)); // Pt.FontName string font = (string)paragraph.Attributes(PtOpenXml.FontName).FirstOrDefault(); if (font != null) CreateFontCssProperty(font, style); // W.sz decimal? sz = null; var languageType = (string)paragraph.Attribute(PtOpenXml.LanguageType); if (languageType == "bidi") sz = (decimal?)pPr.Elements(W.rPr).Elements(W.szCs).Attributes(W.val).FirstOrDefault(); else sz = (decimal?)pPr.Elements(W.rPr).Elements(W.sz).Attributes(W.val).FirstOrDefault(); var sizesOfAllRunsInParagraph = paragraph .DescendantsTrimmed(W.txbxContent) .Select(run => { if (run.Name != W.r) return null; var runLanguageType = (string)run.Attribute(PtOpenXml.LanguageType); if (runLanguageType == "bidi") { var runCsSz = (decimal?)run .Elements(W.rPr) .Elements(W.szCs) .Attributes(W.val) .FirstOrDefault(); return runCsSz; } else { var runSz = (decimal?)run .Elements(W.rPr) .Elements(W.sz) .Attributes(W.val) .FirstOrDefault(); return runSz; } }) .Where(runSz => runSz != null); if (sizesOfAllRunsInParagraph.Any()) sz = sizesOfAllRunsInParagraph.Cast<decimal>().Max(); if (sz != null) style.AddIfMissing("font-size", string.Format("{0}pt", sz / 2.0m)); var languageTypeOfAllRunsInParagraph = paragraph .DescendantsTrimmed(W.txbxContent) .Select(run => { if (run.Name != W.r) return null; var runLanguageType = (string)run.Attribute(PtOpenXml.LanguageType); return runLanguageType; }) .Where(runSz => runSz != null); if (!languageTypeOfAllRunsInParagraph.Any(lt => lt == "bidi")) style.AddIfMissing("line-height", "108%"); // vertical text alignment as of December 2013 does not work in any major browsers. var verticalTextAlignment = (string)pPr.Elements(W.textAlignment).Attributes(W.val).FirstOrDefault(); if (verticalTextAlignment != null && verticalTextAlignment != "auto") { if (verticalTextAlignment == "top") style.AddIfMissing("vertical-align", "top"); else if (verticalTextAlignment == "center") style.AddIfMissing("vertical-align", "middle"); else if (verticalTextAlignment == "baseline") style.AddIfMissing("vertical-align", "baseline"); else if (verticalTextAlignment == "bottom") style.AddIfMissing("vertical-align", "bottom"); } style.AddIfMissing("margin-top", "0pt"); style.AddIfMissing("margin-left", "0pt"); style.AddIfMissing("margin-right", "0pt"); style.AddIfMissing("margin-bottom", ".001pt"); } XAttribute rtl = null; XEntity firstMark = null; if (isBidi) { rtl = new XAttribute("dir", "rtl"); firstMark = new XEntity("#x200f"); // RLM } else { rtl = new XAttribute("dir", "ltr"); } var paraElement = new XElement(elementName, rtl, firstMark, ConvertContentThatCanContainFields(wordDoc, settings, paragraph.Elements())); paraElement.AddAnnotation(style); return paraElement; }
public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) { var record = (OptimizedStaticResourceRecord)((BamlRecordNode)node).Record; var bamlElem = new BamlElement(node); object key; if (record.IsType) { var value = ctx.ResolveType(record.ValueId); var typeElem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml)); typeElem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), ctx.ToString(parent.Xaml, value))); key = typeElem; } else if (record.IsStatic) { string attrName; if (record.ValueId > 0x7fff) { bool isKey = true; short bamlId = (short)-record.ValueId; if (bamlId > 232 && bamlId < 464) { bamlId -= 232; isKey = false; } else if (bamlId > 464 && bamlId < 467) { bamlId -= 231; } else if (bamlId > 467 && bamlId < 470) { bamlId -= 234; isKey = false; } var res = ctx.Baml.KnownThings.Resources(bamlId); string name; if (isKey) name = res.Item1 + "." + res.Item2; else name = res.Item1 + "." + res.Item3; var xmlns = ctx.GetXmlNamespace("http://schemas.microsoft.com/winfx/2006/xaml/presentation"); attrName = ctx.ToString(parent.Xaml, xmlns.GetName(name)); } else { var value = ctx.ResolveProperty(record.ValueId); value.DeclaringType.ResolveNamespace(parent.Xaml, ctx); var xName = value.ToXName(ctx, parent.Xaml); attrName = ctx.ToString(parent.Xaml, xName); } var staticElem = new XElement(ctx.GetXamlNsName("StaticExtension", parent.Xaml)); staticElem.AddAnnotation(ctx.ResolveType(0xfda6)); // Known type - StaticExtension staticElem.Add(new XElement(ctx.GetPseudoName("Ctor"), attrName)); key = staticElem; } else key = ctx.ResolveString(record.ValueId); var extType = ctx.ResolveType(0xfda5); var resElem = new XElement(extType.ToXName(ctx)); resElem.AddAnnotation(extType); // Known type - StaticResourceExtension bamlElem.Xaml = resElem; parent.Xaml.Element.Add(resElem); var attrElem = new XElement(ctx.GetPseudoName("Ctor")); attrElem.Add(key); resElem.Add(attrElem); return bamlElem; }