/// <summary> /// Creates the attribute nodes for the current element and resolves attribute prefixes. /// </summary> /// <returns>An array containing the created attributes.</returns> /// <param name="elementName">The name of the element.</param> private ASXML[] _resolveAttributes(ASQName elementName) { if (m_unresolvedAttrs.length == 0) { return(Array.Empty <ASXML>()); } ASXML[] resolvedAttrs = new ASXML[m_unresolvedAttrs.length]; for (int i = 0, n = m_unresolvedAttrs.length; i < n; i++) { string?prefix = m_unresolvedAttrs[i].prefix; ASNamespace?attributeNamespace = (prefix == null) ? ASNamespace.@public : _resolvePrefix(prefix); if (attributeNamespace == null) { throw _error( ErrorCode.XML_PREFIX_NOT_BOUND, prefix, m_unresolvedAttrs[i].localName, line: m_unresolvedAttrs[i].lineNumber ); } ASQName attributeName = new ASQName(attributeNamespace, m_unresolvedAttrs[i].localName); // Check for duplicate attributes for (int j = 0; j < i; j++) { if (ASQName.AS_equals(attributeName, resolvedAttrs[j].name())) { throw _error( ErrorCode.XML_ATTRIBUTE_DUPLICATE, attributeName.AS_toString(), elementName.AS_toString(), line: m_unresolvedAttrs[i].lineNumber ); } } resolvedAttrs[i] = ASXML.unsafeCreateAttribute(attributeName, m_unresolvedAttrs[i].value); } m_unresolvedAttrs.clear(); return(resolvedAttrs); }
/// <summary> /// Checks if the given <see cref="ASQName"/> is a valid node name for an element, attribute /// or processing instruction. If it is not valid, attempts to create a valid name by removing /// the namespace prefix from the name, or by substituting a default namespace URI if the /// name has a null namespace URI. /// </summary> /// /// <param name="name">The <see cref="ASQName"/> instance to check.</param> /// <param name="nodeType">Must be one of <see cref="XMLNodeType.ELEMENT"/>, <see cref="XMLNodeType.ATTRIBUTE"/> /// or <see cref="XMLNodeType.PROCESSING_INSTRUCTION"/>.</param> /// <param name="defaultNS">The default namespace to use if the namespace URI of <paramref name="name"/> /// is null. If this is null, the value of <see cref="ASNamespace.getDefault()"/> is used if /// <paramref name="nodeType"/> if <see cref="XMLNodeType.ELEMENT"/>, and <see cref="ASNamespace.@public"/> /// otherwise.</param> /// /// <returns>If <paramref name="name"/> is a valid name for a node of the given type, returns /// <paramref name="name"/>; if a new valid name could be created by removing the namespace prefix /// and/or by substituting a default namespace URI, returns the new name; otherwise, returns null.</returns> public static ASQName?tryMakeValidNodeName(ASQName?name, XMLNodeType nodeType, ASNamespace?defaultNS = null) { if (name == null || !isValidName(name.localName)) { return(null); } switch (nodeType) { case XMLNodeType.ELEMENT: if (name.uri == null) { return(new ASQName(defaultNS ?? ASNamespace.getDefault(), name.localName)); } break; case XMLNodeType.PROCESSING_INSTRUCTION: if (name.uri == null || name.uri.Length != 0) { return(new ASQName(ASNamespace.@public, name.localName)); } break; case XMLNodeType.ATTRIBUTE: { if (name.uri == null) { name = new ASQName(defaultNS ?? ASNamespace.@public, name.localName); } else if (name.prefix != null && ((name.prefix.Length == 0 && name.uri.Length != 0) || name.prefix == "xmlns")) { name = ASQName.unsafeCreate(prefix: null, name.uri, name.localName); } if (name.uri !.Length == 0 && name.localName == "xmlns") { return(null); } break; } } return(name); }
private void _enterElement(ASXML elem) { _writeIndent(); ASQName elemName = elem.internalGetName() !; var stackItem = new TagStackItem { tempPrefixIdStart = m_nextTempPrefixId, nsDeclBeginIndex = m_nsInScope.length, localName = elemName.localName, prefix = _getPrefix(elemName, isAttr: false) }; elem.internalGetNamespaceDecls(ref m_nsInScope); m_parts.add("<"); _writeName(stackItem.prefix, stackItem.localName); foreach (ASXML attr in elem.getAttributeEnumerator()) { ASQName attrName = attr.internalGetName() !; string attrValue = attr.nodeText !; m_parts.add(" "); _writeName(_getPrefix(attrName, isAttr: true), attrName.localName); m_parts.add("=\""); m_parts.add(XMLHelper.escape(attrValue, 0, attrValue.Length, ref m_escBuffer, isAttr: true)); m_parts.add("\""); } // If this is the root we must include the ancestor namespaces as well. int nsDeclStart = (m_tagStack.length == 0) ? 0 : stackItem.nsDeclBeginIndex; for (int i = nsDeclStart, n = m_nsInScope.length; i < n; i++) { ASNamespace nsDecl = m_nsInScope[i]; if (nsDecl.prefix !.Length != 0) { m_parts.add(" xmlns:"); m_parts.add(nsDecl.prefix); m_parts.add("=\""); }