/// <summary> /// Create the 'cfvo'/'color' nodes in the right order. They should appear like this: /// "cfvo" --> Low Value (value object) /// "cfvo" --> Middle Value (value object) /// "cfvo" --> High Value (value object) /// "color" --> Low Value (color) /// "color" --> Middle Value (color) /// "color" --> High Value (color) /// </summary> /// <param name="nodeType"></param> /// <param name="attributePath"></param> /// <param name="attributeValue"></param> private void CreateNodeByOrdem( eExcelConditionalFormattingValueObjectNodeType nodeType, string attributePath, string attributeValue) { // Save the current TopNode XmlNode currentTopNode = TopNode; string nodePath = ExcelConditionalFormattingValueObjectType.GetNodePathByNodeType(nodeType); int nodeOrder = GetNodeOrder(); eNodeInsertOrder nodeInsertOrder = eNodeInsertOrder.SchemaOrder; XmlNode referenceNode = null; if (nodeOrder > 1) { // Find the node just before the one we need to include referenceNode = TopNode.SelectSingleNode( string.Format( "{0}[position()={1}]", // {0} nodePath, // {1} nodeOrder - 1), _worksheet.NameSpaceManager); // Only if the prepend node exists than insert after if (referenceNode != null) { nodeInsertOrder = eNodeInsertOrder.After; } } // Create the node in the right order var node = CreateComplexNode( TopNode, string.Format( "{0}[position()={1}]", // {0} nodePath, // {1} nodeOrder), nodeInsertOrder, referenceNode); // Point to the new node as the temporary TopNode (we need it for the XmlHelper functions) TopNode = node; // Add/Remove the attribute (if the attributeValue is empty then it will be removed) SetXmlNodeString( node, attributePath, attributeValue, true); // Point back to the <cfvo>/<color> parent node TopNode = currentTopNode; }
/// <summary> /// Creates complex XML nodes /// </summary> /// <remarks> /// 1. "d:conditionalFormatting" /// 1.1. Creates/find the first "conditionalFormatting" node /// /// 2. "d:conditionalFormatting/@sqref" /// 2.1. Creates/find the first "conditionalFormatting" node /// 2.2. Creates (if not exists) the @sqref attribute /// /// 3. "d:conditionalFormatting/@id='7'/@sqref='A9:B99'" /// 3.1. Creates/find the first "conditionalFormatting" node /// 3.2. Creates/update its @id attribute to "7" /// 3.3. Creates/update its @sqref attribute to "A9:B99" /// /// 4. "d:conditionalFormatting[@id='7']/@sqref='X1:X5'" /// 4.1. Creates/find the first "conditionalFormatting" node with @id=7 /// 4.2. Creates/update its @sqref attribute to "X1:X5" /// /// 5. "d:conditionalFormatting[@id='7']/@id='8'/@sqref='X1:X5'/d:cfRule/@id='AB'" /// 5.1. Creates/find the first "conditionalFormatting" node with @id=7 /// 5.2. Set its @id attribute to "8" /// 5.2. Creates/update its @sqref attribute and set it to "X1:X5" /// 5.3. Creates/find the first "cfRule" node (inside the node) /// 5.4. Creates/update its @id attribute to "AB" /// /// 6. "d:cfRule/@id=''" /// 6.1. Creates/find the first "cfRule" node /// 6.1. Remove the @id attribute /// </remarks> /// <param name="topNode"></param> /// <param name="path"></param> /// <param name="nodeInsertOrder"></param> /// <param name="referenceNode"></param> /// <returns>The last node creates/found</returns> internal XmlNode CreateComplexNode( XmlNode topNode, string path, eNodeInsertOrder nodeInsertOrder, XmlNode referenceNode) { // Path is obrigatory if ((path == null) || (path == string.Empty)) { return topNode; } XmlNode node = topNode; string nameSpaceURI = string.Empty; //TODO: BUG: when the "path" contains "/" in an attrribue value, it gives an error. // Separate the XPath to Nodes and Attributes foreach (string subPath in path.Split('/')) { // The subPath can be any one of those: // nodeName // x:nodeName // nodeName[find criteria] // x:nodeName[find criteria] // @attribute // @attribute='attribute value' // Check if the subPath has at least one character if (subPath.Length > 0) { // Check if the subPath is an attribute (with or without value) if (subPath.StartsWith("@")) { // @attribute --> Create attribute // @attribute='' --> Remove attribute // @attribute='attribute value' --> Create attribute + update value string[] attributeSplit = subPath.Split('='); string attributeName = attributeSplit[0].Substring(1, attributeSplit[0].Length - 1); string attributeValue = null; // Null means no attribute value // Check if we have an attribute value to set if (attributeSplit.Length > 1) { // Remove the ' or " from the attribute value attributeValue = attributeSplit[1].Replace("'", "").Replace("\"", ""); } // Get the attribute (if exists) XmlAttribute attribute = (XmlAttribute)(node.Attributes.GetNamedItem(attributeName)); // Remove the attribute if value is empty (not null) if (attributeValue == string.Empty) { // Only if the attribute exists if (attribute != null) { node.Attributes.Remove(attribute); } } else { // Create the attribue if does not exists if (attribute == null) { // Create the attribute attribute = node.OwnerDocument.CreateAttribute( attributeName); // Add it to the current node node.Attributes.Append(attribute); } // Update the attribute value if (attributeValue != null) { node.Attributes[attributeName].Value = attributeValue; } } } else { // nodeName // x:nodeName // nodeName[find criteria] // x:nodeName[find criteria] // Look for the node (with or without filter criteria) XmlNode subNode = node.SelectSingleNode(subPath, NameSpaceManager); // Check if the node does not exists if (subNode == null) { string nodeName; string nodePrefix; string[] nameSplit = subPath.Split(':'); nameSpaceURI = string.Empty; // Check if the name has a prefix like "d:nodeName" if (nameSplit.Length > 1) { nodePrefix = nameSplit[0]; nameSpaceURI = NameSpaceManager.LookupNamespace(nodePrefix); nodeName = nameSplit[1]; } else { nodePrefix = string.Empty; nameSpaceURI = string.Empty; nodeName = nameSplit[0]; } // Check if we have a criteria part in the node name if (nodeName.IndexOf("[") > 0) { // remove the criteria from the node name nodeName = nodeName.Substring(0, nodeName.IndexOf("[")); } if (nodePrefix == string.Empty) { subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceURI); } else { if (node.OwnerDocument != null && node.OwnerDocument.DocumentElement != null && node.OwnerDocument.DocumentElement.NamespaceURI == nameSpaceURI && node.OwnerDocument.DocumentElement.Prefix == string.Empty) { subNode = node.OwnerDocument.CreateElement( nodeName, nameSpaceURI); } else { subNode = node.OwnerDocument.CreateElement( nodePrefix, nodeName, nameSpaceURI); } } // Check if we need to use the "SchemaOrder" if (nodeInsertOrder == eNodeInsertOrder.SchemaOrder) { // Check if the Schema Order List is empty if ((SchemaNodeOrder == null) || (SchemaNodeOrder.Length == 0)) { // Use the "Insert Last" option when Schema Order List is empty nodeInsertOrder = eNodeInsertOrder.Last; } else { // Find the prepend node in order to insert referenceNode = GetPrependNode(nodeName, node); if (referenceNode != null) { nodeInsertOrder = eNodeInsertOrder.Before; } else { nodeInsertOrder = eNodeInsertOrder.Last; } } } switch (nodeInsertOrder) { case eNodeInsertOrder.After: node.InsertAfter(subNode, referenceNode); referenceNode = null; break; case eNodeInsertOrder.Before: node.InsertBefore(subNode, referenceNode); referenceNode = null; break; case eNodeInsertOrder.First: node.PrependChild(subNode); break; case eNodeInsertOrder.Last: node.AppendChild(subNode); break; } } // Make the newly created node the top node when the rest of the path // is being evaluated. So newly created nodes will be the children of the // one we just created. node = subNode; } } } // Return the last created/found node return node; }
/// <summary> /// Creates complex XML nodes /// </summary> /// <remarks> /// 1. "d:conditionalFormatting" /// 1.1. Creates/find the first "conditionalFormatting" node /// /// 2. "d:conditionalFormatting/@sqref" /// 2.1. Creates/find the first "conditionalFormatting" node /// 2.2. Creates (if not exists) the @sqref attribute /// /// 3. "d:conditionalFormatting/@id='7'/@sqref='A9:B99'" /// 3.1. Creates/find the first "conditionalFormatting" node /// 3.2. Creates/update its @id attribute to "7" /// 3.3. Creates/update its @sqref attribute to "A9:B99" /// /// 4. "d:conditionalFormatting[@id='7']/@sqref='X1:X5'" /// 4.1. Creates/find the first "conditionalFormatting" node with @id=7 /// 4.2. Creates/update its @sqref attribute to "X1:X5" /// /// 5. "d:conditionalFormatting[@id='7']/@id='8'/@sqref='X1:X5'/d:cfRule/@id='AB'" /// 5.1. Creates/find the first "conditionalFormatting" node with @id=7 /// 5.2. Set its @id attribute to "8" /// 5.2. Creates/update its @sqref attribute and set it to "X1:X5" /// 5.3. Creates/find the first "cfRule" node (inside the node) /// 5.4. Creates/update its @id attribute to "AB" /// /// 6. "d:cfRule/@id=''" /// 6.1. Creates/find the first "cfRule" node /// 6.1. Remove the @id attribute /// </remarks> /// <param name="topNode"></param> /// <param name="path"></param> /// <param name="nodeInsertOrder"></param> /// <param name="referenceNode"></param> /// <returns>The last node creates/found</returns> internal XmlNode CreateComplexNode( XmlNode topNode, string path, eNodeInsertOrder nodeInsertOrder, XmlNode referenceNode) { // Path is obrigatory if ((path == null) || (path == string.Empty)) { return(topNode); } XmlNode node = topNode; string nameSpaceURI = string.Empty; //TODO: BUG: when the "path" contains "/" in an attrribue value, it gives an error. // Separate the XPath to Nodes and Attributes foreach (string subPath in path.Split('/')) { // The subPath can be any one of those: // nodeName // x:nodeName // nodeName[find criteria] // x:nodeName[find criteria] // @attribute // @attribute='attribute value' // Check if the subPath has at least one character if (subPath.Length > 0) { // Check if the subPath is an attribute (with or without value) if (subPath.StartsWith("@")) { // @attribute --> Create attribute // @attribute='' --> Remove attribute // @attribute='attribute value' --> Create attribute + update value string[] attributeSplit = subPath.Split('='); string attributeName = attributeSplit[0].Substring(1, attributeSplit[0].Length - 1); string attributeValue = null; // Null means no attribute value // Check if we have an attribute value to set if (attributeSplit.Length > 1) { // Remove the ' or " from the attribute value attributeValue = attributeSplit[1].Replace("'", "").Replace("\"", ""); } // Get the attribute (if exists) XmlAttribute attribute = (XmlAttribute)(node.Attributes.GetNamedItem(attributeName)); // Remove the attribute if value is empty (not null) if (attributeValue == string.Empty) { // Only if the attribute exists if (attribute != null) { node.Attributes.Remove(attribute); } } else { // Create the attribue if does not exists if (attribute == null) { // Create the attribute attribute = node.OwnerDocument.CreateAttribute( attributeName); // Add it to the current node node.Attributes.Append(attribute); } // Update the attribute value if (attributeValue != null) { node.Attributes[attributeName].Value = attributeValue; } } } else { // nodeName // x:nodeName // nodeName[find criteria] // x:nodeName[find criteria] // Look for the node (with or without filter criteria) XmlNode subNode = node.SelectSingleNode(subPath, NameSpaceManager); // Check if the node does not exists if (subNode == null) { string nodeName; string nodePrefix; string[] nameSplit = subPath.Split(':'); nameSpaceURI = string.Empty; // Check if the name has a prefix like "d:nodeName" if (nameSplit.Length > 1) { nodePrefix = nameSplit[0]; nameSpaceURI = NameSpaceManager.LookupNamespace(nodePrefix); nodeName = nameSplit[1]; } else { nodePrefix = string.Empty; nameSpaceURI = string.Empty; nodeName = nameSplit[0]; } // Check if we have a criteria part in the node name if (nodeName.IndexOf("[") > 0) { // remove the criteria from the node name nodeName = nodeName.Substring(0, nodeName.IndexOf("[")); } if (nodePrefix == string.Empty) { subNode = node.OwnerDocument.CreateElement(nodeName, nameSpaceURI); } else { if (node.OwnerDocument != null && node.OwnerDocument.DocumentElement != null && node.OwnerDocument.DocumentElement.NamespaceURI == nameSpaceURI && node.OwnerDocument.DocumentElement.Prefix == string.Empty) { subNode = node.OwnerDocument.CreateElement( nodeName, nameSpaceURI); } else { subNode = node.OwnerDocument.CreateElement( nodePrefix, nodeName, nameSpaceURI); } } // Check if we need to use the "SchemaOrder" if (nodeInsertOrder == eNodeInsertOrder.SchemaOrder) { // Check if the Schema Order List is empty if ((SchemaNodeOrder == null) || (SchemaNodeOrder.Length == 0)) { // Use the "Insert Last" option when Schema Order List is empty nodeInsertOrder = eNodeInsertOrder.Last; } else { // Find the prepend node in order to insert referenceNode = GetPrependNode(nodeName, node); if (referenceNode != null) { nodeInsertOrder = eNodeInsertOrder.Before; } else { nodeInsertOrder = eNodeInsertOrder.Last; } } } switch (nodeInsertOrder) { case eNodeInsertOrder.After: node.InsertAfter(subNode, referenceNode); referenceNode = null; break; case eNodeInsertOrder.Before: node.InsertBefore(subNode, referenceNode); referenceNode = null; break; case eNodeInsertOrder.First: node.PrependChild(subNode); break; case eNodeInsertOrder.Last: node.AppendChild(subNode); break; } } // Make the newly created node the top node when the rest of the path // is being evaluated. So newly created nodes will be the children of the // one we just created. node = subNode; } } } // Return the last created/found node return(node); }