in sources/java-incremental-compilation/jvm-inc-builder/src/com/intellij/tools/build/bazel/org/jdom/input/DOMBuilder.java [220:439]
private void buildTree(Node node,
Document doc,
Element current,
boolean atRoot) {
// Recurse through the tree
switch (node.getNodeType()) {
case Node.DOCUMENT_NODE:
NodeList nodes = node.getChildNodes();
for (int i = 0, size = nodes.getLength(); i < size; i++) {
buildTree(nodes.item(i), doc, current, true);
}
break;
case Node.ELEMENT_NODE:
String nodeName = node.getNodeName();
String prefix = NS_PREFIX_DEFAULT;
String localName = nodeName;
int colon = nodeName.indexOf(':');
if (colon >= 0) {
prefix = nodeName.substring(0, colon);
localName = nodeName.substring(colon + 1);
}
// Get element's namespace
Namespace ns;
String uri = node.getNamespaceURI();
if (uri == null) {
ns = (current == null) ? Namespace.NO_NAMESPACE
: current.getNamespace(prefix);
}
else {
ns = Namespace.getNamespace(prefix, uri);
}
Element element = factory.element(localName, ns);
if (atRoot) {
// If at root, set as document root
factory.setRoot(doc, element);
}
else {
// else add to a parent element
factory.addContent(current, element);
}
// Add namespaces
NamedNodeMap attributeList = node.getAttributes();
int attsize = attributeList.getLength();
for (int i = 0; i < attsize; i++) {
Attr att = (Attr)attributeList.item(i);
String attname = att.getName();
if (attname.startsWith(NS_PREFIX_XMLNS)) {
String attPrefix = NS_PREFIX_DEFAULT;
colon = attname.indexOf(':');
if (colon >= 0) {
attPrefix = attname.substring(colon + 1);
}
String attvalue = att.getValue();
Namespace declaredNS =
Namespace.getNamespace(attPrefix, attvalue);
// Add as additional namespaces if it's different
// to this element's namespace (perhaps we should
// also have logic not to mark them as additional if
// it's been done already, but it probably doesn't
// matter)
if (prefix.equals(attPrefix)) {
// RL: note, it should also be true that uri.equals(attvalue)
// if not, then the parser is boken.
// further, declaredNS should be exactly the same as ns
// so the following should, in fact do nothing.
element.setNamespace(declaredNS);
}
else {
factory.addNamespaceDeclaration(element, declaredNS);
}
}
}
// Add attributes
for (int i = 0; i < attsize; i++) {
Attr att = (Attr)attributeList.item(i);
String attname = att.getName();
if (!attname.startsWith(NS_PREFIX_XMLNS)) {
String attPrefix = NS_PREFIX_DEFAULT;
String attLocalName = attname;
colon = attname.indexOf(':');
if (colon >= 0) {
attPrefix = attname.substring(0, colon);
attLocalName = attname.substring(colon + 1);
}
String attvalue = att.getValue();
// Get attribute's namespace
Namespace attNS = null;
String attURI = att.getNamespaceURI();
if (attPrefix.isEmpty() && (attURI == null || NS_URI_DEFAULT.equals(attURI))) {
attNS = Namespace.NO_NAMESPACE;
}
else {
// various conditions can lead here.
// the logical one is that we have a prefix for the
// attribute, and also a namespace URI.
// The alternative to that is in some conditions,
// the parser could have a 'default' or 'fixed'
// attribute that comes from an XSD used for
// validation. In that case, there may not be a prefix
// There's also the possibility the DOM contains
// garbage.
if (!attPrefix.isEmpty()) {
// If the att has a prefix, we can assume that
// the DOM is valid, and we can just use the prefix.
// if this prefix conflicts with some other namespace
// then we re-declare it. If redeclaring it screws up
// other attributes in this Element, then the DOM
// was broken to start with.
if (attURI == null) {
// this can happen when the DOM is created
// without being namespace aware. we have a
// prefix, but the URI is not embedded in
// the Attribute itself. It must be declared
// on the element somewhere....
// https://github.com/hunterhacker/jdom/issues/138
attNS = element.getNamespace(attPrefix);
}
else {
attNS = Namespace.getNamespace(attPrefix, attURI);
}
}
else {
// OK, no prefix.
// must be a defaulted value from an XSD.
// perhaps we can find the namespace in our
// element's ancestry, and use the prefix from that.
HashMap<String, Namespace> tmpmap = new HashMap<>();
for (Namespace nss : element.getNamespacesInScope()) {
if (!nss.getPrefix().isEmpty() && nss.getURI().equals(attURI)) {
attNS = nss;
break;
}
tmpmap.put(nss.getPrefix(), nss);
}
if (attNS == null) {
// we cannot find a 'prevailing' namespace that has a prefix
// that is for this namespace.
// This basically means that there's an XMLSchema, for the
// DEFAULT namespace, and there's a defaulted/fixed
// attribute definition in the XMLSchema that's targeted
// for this namespace,... but, the user has either not
// declared a prefixed version of the namespace, or has
// re-declared the same prefix at a lower level with a
// different namespace.
// All of these things are possible.
// Create some sort of default prefix.
int cnt = 0;
String base = "attns";
String pfx = base + cnt;
while (tmpmap.containsKey(pfx)) {
cnt++;
pfx = base + cnt;
}
attNS = Namespace.getNamespace(pfx, attURI);
}
}
}
Attribute attribute =
factory.attribute(attLocalName, attvalue, attNS);
factory.setAttribute(element, attribute);
}
}
// Recurse on child nodes
// The list should never be null nor should it ever contain
// null nodes, but some DOM impls are broken
NodeList children = node.getChildNodes();
int size = children.getLength();
for (int i = 0; i < size; i++) {
Node item = children.item(i);
if (item != null) {
buildTree(item, doc, element, false);
}
}
break;
case Node.TEXT_NODE:
factory.addContent(current, build((Text)node));
break;
case Node.CDATA_SECTION_NODE:
factory.addContent(current, build((CDATASection)node));
break;
case Node.PROCESSING_INSTRUCTION_NODE:
case Node.COMMENT_NODE:
break;
case Node.ENTITY_REFERENCE_NODE:
factory.addContent(current, build((EntityReference)node));
break;
case Node.ENTITY_NODE:
// ??
break;
case Node.DOCUMENT_TYPE_NODE:
factory.addContent(doc, build((DocumentType)node));
break;
}
}