/// <summary> /// Adds given node to <see cref="Content"/>. /// </summary> /// <param name="node">Child node to add to Content.</param> /// <returns>Current container.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidNodeException"></exception> /// <exception cref="UnexpectedNodeException"></exception> public Fb2Container AddContent(Fb2Node node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (!Fb2NodeFactory.IsKnownNode(node)) { throw new InvalidNodeException(node); } var nodeName = node.Name; var isTextNode = node is TextItem; if (isTextNode && !CanContainText) { throw new UnexpectedNodeException(Name, nodeName); } if (!AllowedElements.Contains(nodeName) && !isTextNode) { throw new UnexpectedNodeException(Name, nodeName); } if (isTextNode) { return(TryMergeTextContent((node as TextItem) !.Content)); } node.Parent = this; if (node.NodeMetadata == null && NodeMetadata?.DefaultNamespace != null) // copy parent default namespace to prevent serialization issues { node.NodeMetadata = new Fb2NodeMetadata(NodeMetadata?.DefaultNamespace); } content.Add(node); return(this); }
/// <summary> /// Container node loading mechanism. Loads attributes and sequentially calls `Load` on all child nodes. /// </summary> /// <param name="node">Node to load as Fb2Container</param> /// <param name="preserveWhitespace">Indicates if whitespace chars (\t, \n, \r) should be preserved. By default `false`.</param> /// <param name="loadUnsafe">Indicates whether "Unsafe" children should be loaded. By default `true`. </param> public override void Load( [In] XNode node, [In] Fb2Container?parentNode = null, bool preserveWhitespace = false, bool loadUnsafe = true, bool loadNamespaceMetadata = true) { base.Load(node, parentNode, preserveWhitespace, loadUnsafe, loadNamespaceMetadata); var element = node as XElement; if (element == null || element.IsEmpty) { return; } var nodes = element.Nodes() .Where(n => { if (n.NodeType == XmlNodeType.Text) { return(true); } var isElement = n.NodeType == XmlNodeType.Element; if (!isElement) { return(false); } var elementNode = n as XElement; var nodeLocalName = elementNode.Name.LocalName; return(!nodeLocalName.EqualsIgnoreCase(ElementNames.FictionText) && Fb2NodeFactory.IsKnownNodeName(nodeLocalName)); }) .ToList(); var nodesCount = nodes.Count; if (nodesCount == 0) { return; } for (int i = 0; i < nodesCount; i++) { var validNode = nodes[i]; string localName = validNode.NodeType == XmlNodeType.Element ? ((XElement)validNode).Name.LocalName.ToLowerInvariant() : ElementNames.FictionText; var isUnsafe = validNode.NodeType == XmlNodeType.Text ? !CanContainText : !AllowedElements.Contains(localName); if (isUnsafe && !loadUnsafe) { continue; } var elem = Fb2NodeFactory.GetNodeByName(localName); elem.Load(validNode, this, preserveWhitespace, loadUnsafe, loadNamespaceMetadata); elem.IsUnsafe = isUnsafe; content.Add(elem); } }