/// <summary> /// When overridden in a derived class, creates a duplicate of the node. /// </summary> /// <param name="deep"> /// Specify true to recursively clone the subtree under the specified /// node; false to clone only the node itself. /// </param> /// <returns>The cloned node. </returns> public override OpenXmlElement CloneNode(bool deep) { OpenXmlMiscNode element = new OpenXmlMiscNode(this.XmlNodeType); element.OuterXml = this.OuterXml; return(element); }
internal static OpenXmlMiscNode CreateFromSignificantWhitespace(string whitespace) { Debug.Assert(whitespace != null); var newMiscNode = new OpenXmlMiscNode(XmlNodeType.SignificantWhitespace); newMiscNode.Value = whitespace; newMiscNode.RawOuterXml = whitespace; return(newMiscNode); }
internal static OpenXmlMiscNode CreateFromCdata(string value) { Debug.Assert(value != null); var newMiscNode = new OpenXmlMiscNode(XmlNodeType.CDATA); newMiscNode.Value = value; newMiscNode.RawOuterXml = string.Format(CultureInfo.InvariantCulture, "<![CDATA[{0}]]>", value); return(newMiscNode); }
internal static OpenXmlMiscNode CreateFromText(string text) { Debug.Assert(text != null); var newMiscNode = new OpenXmlMiscNode(XmlNodeType.Text); newMiscNode.Value = text; newMiscNode.RawOuterXml = text; return(newMiscNode); }
internal override void Populate(XmlReader xmlReader, OpenXmlLoadMode loadMode) { if (String.IsNullOrEmpty(this._tagName)) { this._tagName = xmlReader.LocalName; this._prefix = xmlReader.Prefix; this._namespaceUri = xmlReader.NamespaceURI; } else { Debug.Assert(String.Equals(this._tagName, xmlReader.LocalName)); Debug.Assert(String.Equals(this._prefix, xmlReader.Prefix)); Debug.Assert(String.Equals(this._namespaceUri, xmlReader.NamespaceURI)); } // load children elements base.Populate(xmlReader, loadMode); if (this.FirstChild != null && this.FirstChild.NextSibling() == null) { // only one child OpenXmlMiscNode miscNode = this.FirstChild as OpenXmlMiscNode; if (miscNode != null) { switch (miscNode.XmlNodeType) { case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: this._text = miscNode.OuterXml; // is this OK? this.RemoveChild(miscNode); break; case XmlNodeType.Whitespace: // O15:#3024890, OpenXmlUnknownElement ignores the Whitespace NodeType. default: break; } } } }
//internal override void Load(XmlReader xmlReader) //{ // LoadAttributes(xmlReader); // this.Text = xmlReader.ReadElementString(); //} internal override void Populate(XmlReader xmlReader, OpenXmlLoadMode loadMode) { LoadAttributes(xmlReader); if (!xmlReader.IsEmptyElement) { // only when element is not empty (not <element />). xmlReader.Read(); // read this element this.RawInnerText = string.Empty; int unwanted = 0; int textNodePosition = -1; // the position of the text in the ShadowElement's children when there are other unexpected node. XmlNodeType textNodeType = XmlNodeType.Text; if (xmlReader.NodeType == XmlNodeType.EndElement) { Debug.Assert(xmlReader.LocalName.Equals(this.LocalName)); } else { while (!xmlReader.EOF) { if (xmlReader.NodeType == XmlNodeType.EndElement) { Debug.Assert(xmlReader.LocalName.Equals(this.LocalName)); break; } else if (string.IsNullOrEmpty(this.RawInnerText) && (xmlReader.NodeType == XmlNodeType.Text || xmlReader.NodeType == XmlNodeType.CDATA || xmlReader.NodeType == XmlNodeType.SignificantWhitespace || xmlReader.NodeType == XmlNodeType.Whitespace /* O15:#3024890 */)) { // text or CDATA // scenario: normal text element <Application>Microsoft Office Word</Application> // scenario: <w:t>This is <![CDATA[Xml Example <tag>text</tag>.]]> 1</w:t> // only load text when no text is loaded, // for case "<foo/>Text1<bar/>Text2", only load "Text1", very rare case this.RawInnerText = xmlReader.Value; textNodePosition = unwanted; textNodeType = xmlReader.NodeType; xmlReader.Read(); } else { Debug.Assert(xmlReader.NodeType != XmlNodeType.EntityReference); // Load unexpected children if there are any. OpenXmlElement child = this.ElementFactory(xmlReader); child.Load(xmlReader, OpenXmlLoadMode.Full); unwanted++; if (this.ShadowElement == null) { this.ShadowElement = new OpenXmlUnknownElement(this.Prefix, this.LocalName, this.NamespaceUri); } this.ShadowElement.AppendChild(child); } } } if (unwanted == 0) { // only text node, no unwanted children Debug.Assert(this.ShadowElement == null); } else if (textNodePosition > -1) { // place an OpenXmlMiscNode for the loaded text in the ShadowElement so that we can write out correct content in serialization. OpenXmlMiscNode textNode = null; switch (textNodeType) { case XmlNodeType.Text: textNode = OpenXmlMiscNode.CreateFromText(this.RawInnerText); break; case XmlNodeType.CDATA: textNode = OpenXmlMiscNode.CreateFromCdata(this.RawInnerText); break; case XmlNodeType.SignificantWhitespace: case XmlNodeType.Whitespace: /* O15:#3024890 */ textNode = OpenXmlMiscNode.CreateFromSignificantWhitespace(this.RawInnerText); break; } this.ShadowElement.InsertAt(textNode, textNodePosition); } else { // textNodePosition == -1, no text loaded. } } xmlReader.Skip(); // skip the end tag // set raw outer xml to empty to indicate that it is passed this.RawOuterXml = string.Empty; }
internal static OpenXmlMiscNode CreateFromSignificantWhitespace(string whitespace) { Debug.Assert(whitespace != null); var newMiscNode = new OpenXmlMiscNode(XmlNodeType.SignificantWhitespace); newMiscNode.Value = whitespace; newMiscNode.RawOuterXml = whitespace; return newMiscNode; }
internal static OpenXmlMiscNode CreateFromCdata(string value) { Debug.Assert(value != null); var newMiscNode = new OpenXmlMiscNode(XmlNodeType.CDATA); newMiscNode.Value = value; newMiscNode.RawOuterXml = String.Format(CultureInfo.InvariantCulture, "<![CDATA[{0}]]>", value); ; return newMiscNode; }
internal static OpenXmlMiscNode CreateFromText(string text) { Debug.Assert(text != null); var newMiscNode = new OpenXmlMiscNode(XmlNodeType.Text); newMiscNode.Value = text; newMiscNode.RawOuterXml = text; return newMiscNode; }
/// <summary> /// When overridden in a derived class, creates a duplicate of the node. /// </summary> /// <param name="deep"> /// Specify true to recursively clone the subtree under the specified /// node; false to clone only the node itself. /// </param> /// <returns>The cloned node. </returns> public override OpenXmlElement CloneNode(bool deep) { OpenXmlMiscNode element = new OpenXmlMiscNode(this.XmlNodeType); element.OuterXml = this.OuterXml; return element; }
public void ElementCloneTest() { using(MemoryStream stream = new MemoryStream(TestFileStreams.mcdoc)) using (var doc = WordprocessingDocument.Open(stream, false)) { // Shallow clone the body, which doesn't have attributes var body = doc.MainDocumentPart.Document.Body; var clonedBody = body.CloneNode(false); Assert.False(clonedBody.HasChildren); Assert.Equal(body.HasAttributes, clonedBody.HasAttributes); //Cloned Body has no attributes. Assert.Equal(body.ExtendedAttributes.Count(), clonedBody.ExtendedAttributes.Count()); // Shallow clone the first paragraph, which has attributes var paragraph = body.Descendants<Paragraph>().First(); var clonedParagraph = paragraph.CloneNode(false); Assert.False(clonedParagraph.HasChildren); Assert.True(clonedParagraph.HasAttributes); Assert.Equal(paragraph.Attributes.Count(), clonedParagraph.Attributes.Count()); Assert.Equal(paragraph.ExtendedAttributes.Count(), clonedParagraph.ExtendedAttributes.Count()); // Deep clone the document var clonedDocument = doc.MainDocumentPart.Document.CloneNode(true); Assert.True(clonedDocument.HasChildren); Assert.Equal(doc.MainDocumentPart.Document.ChildElements.Count, clonedDocument.ChildElements.Count); Assert.Equal(doc.MainDocumentPart.Document.Descendants().Count(), clonedDocument.Descendants().Count()); var docEnumerator = doc.MainDocumentPart.Document.Descendants().GetEnumerator(); foreach (var elem in clonedDocument.Descendants()) { Assert.True(docEnumerator.MoveNext()); var curElem = docEnumerator.Current; Assert.Equal(curElem.GetType(), elem.GetType()); Assert.Equal(curElem.NamespaceUri, elem.NamespaceUri); Assert.Equal(curElem.XmlQualifiedName, elem.XmlQualifiedName); Assert.Equal(curElem.Attributes == null, elem.Attributes == null); if (curElem.Attributes != null) { Assert.Equal(curElem.Attributes.Length, elem.Attributes.Length); } Assert.Equal(curElem.ExtendedAttributes.Count(), elem.ExtendedAttributes.Count()); var a1 = curElem.ExtendedAttributes.ToArray(); var a2 = elem.ExtendedAttributes.ToArray(); for(int i = 0; i< a1.Length; i++) { Assert.Equal(a1[i].NamespaceUri, a2[i].NamespaceUri); Assert.Equal(a1[i].LocalName, a2[i].LocalName); Assert.Equal(a1[i].Value, a2[i].Value); } Assert.Equal(curElem.MCAttributes == null, elem.MCAttributes == null); if (curElem is OpenXmlLeafTextElement) { Assert.Equal(((OpenXmlLeafTextElement)curElem).Text, ((OpenXmlLeafTextElement)elem).Text); } } // Deep clone the unknown element var unknown = doc.MainDocumentPart.Document.Descendants<OpenXmlUnknownElement>().Where(e => e.LocalName == "wsp").First(); var clonedUnknown = unknown.CloneNode(true); Assert.Equal(unknown.OuterXml, clonedUnknown.OuterXml); // Clone the OpenXmlMiscNode var miscNode = new OpenXmlMiscNode(System.Xml.XmlNodeType.Comment, "<!-- my comment -->"); var clonedMiscNode = miscNode.CloneNode(true) as OpenXmlMiscNode; Assert.NotNull(clonedMiscNode); Assert.Equal(miscNode.XmlNodeType, clonedMiscNode.XmlNodeType); Assert.Equal(miscNode.OuterXml, clonedMiscNode.OuterXml); // Shallow clone mc element var acb = body.Descendants<AlternateContent>().First(); acb.MCAttributes = new MarkupCompatibilityAttributes(); acb.MCAttributes.Ignorable = "w14"; acb.MCAttributes.MustUnderstand = "wp"; acb.MCAttributes.PreserveAttributes = "a"; acb.MCAttributes.PreserveElements = "w14"; acb.MCAttributes.ProcessContent = "wp"; var clonedAcb = acb.CloneNode(false); Assert.NotNull(clonedAcb.MCAttributes); Assert.Equal(acb.MCAttributes.Ignorable.Value, clonedAcb.MCAttributes.Ignorable.Value); Assert.Equal(acb.MCAttributes.MustUnderstand.Value, clonedAcb.MCAttributes.MustUnderstand.Value); Assert.Equal(acb.MCAttributes.PreserveAttributes.Value, clonedAcb.MCAttributes.PreserveAttributes.Value); Assert.Equal(acb.MCAttributes.PreserveElements.Value, clonedAcb.MCAttributes.PreserveElements.Value); Assert.Equal(acb.MCAttributes.ProcessContent.Value, clonedAcb.MCAttributes.ProcessContent.Value); } }