All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.softicar.platform.common.io.xml.parser.XmlNode Maven / Gradle / Ivy

Go to download

The SoftiCAR Platform is a lightweight, Java-based library to create interactive business web applications.

There is a newer version: 50.0.0
Show newest version
package com.softicar.platform.common.io.xml.parser;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * Represents a node in an XML tree.
 * 

* Allows for convenient retrieval of nodes, attributes, and textual content. *

* Instances should be obtained via {@link XmlParser}. * * @author Alexander Schmidt */ public class XmlNode { private final List children; private final String tag; private final XmlNode parent; private final Map attributes; private final String content; private final int depth; XmlNode(String tag, Map attributes, String content, XmlNode parent, int depth) { this.children = new ArrayList<>(); this.tag = tag; this.parent = parent; this.attributes = attributes; this.content = content.trim(); this.depth = depth; } /** * Returns the {@link String} representation of the tag of this * {@link XmlNode}. * * @return the tag of this {@link XmlNode} (never null) */ public String getTag() { return tag; } /** * Returns a {@link Map} from attribute name to the respective attribute * values of this {@link XmlNode}. * * @return the attribute-value map of this {@link XmlNode} (never * null) */ public Map getAttributes() { return attributes; } /** * Returns the trimmed textual content of this {@link XmlNode}. *

* Returns an empty {@link String} if this {@link XmlNode} has no textual * content. * * @return the textual content of this {@link XmlNode} (never null) */ public String getTextContent() { return content; } /** * Returns the parent {@link XmlNode} of this {@link XmlNode}. *

* If this {@link XmlNode} does not have a parent (i.e. if it is a root), * null is returned. * * @return the parent of this {@link XmlNode} (may be null) */ public XmlNode getParent() { return parent; } /** * Returns the depth of this {@link XmlNode} in the XML tree. *

* The root {@link XmlNode} has a depth of 0. * * @return the depth of this {@link XmlNode} */ public int getDepth() { return depth; } // -------------------------------- children -------------------------------- // /** * Returns the immediate children of this {@link XmlNode}. *

* If this {@link XmlNode} has no children, an empty {@link List} is * returned. * * @return the children of this {@link XmlNode} (never null) */ public List getChildren() { return children; } /** * Returns the number of immediate children of this {@link XmlNode}. * * @return the number of children */ public int getChildCount() { return getChildren().size(); } /** * Returns a {@link List} of all immediate child {@link XmlNode}s with the * given tag. * * @param tag * the literal tag of the child {@link XmlNode}s to find (never * null) * @return the child {@link XmlNode}s with the given tag (never null) */ public List getChildrenWithTag(String tag) { List childrenByTag = new ArrayList<>(); for (XmlNode child: getChildren()) { if (child.getTag().equals(tag.toString())) { childrenByTag.add(child); } } return childrenByTag; } /** * Returns a {@link List} of all immediate child {@link XmlNode}s with the * given tag. * * @param tag * the {@link IXmlTag} of the child {@link XmlNode}s to find * (never null) * @return the child {@link XmlNode}s with the given tag (never null) */ public List getChildrenWithTag(IXmlTag tag) { return getChildrenWithTag(tag.getName()); } // -------------------------------- path-based transitive children -------------------------------- // /** * Fetches a single {@link XmlNode}, located at the end of the path * specified by the given tag {@link String} arguments. *

* Each of the given path tokens may optionally contain an encoded index * (see {@link XmlTag#create(String)} for details). *

* If a token in the given path does not contain an index, and if it matches * several possible nodes, the first of those nodes is chosen. *

* Returns {@link Optional#empty()} in case no node could be found at the * given path. * * @param path * one or several XML tag literals which describe the path to the * transitive child {@link XmlNode} to be found * @return the node found at the end of the given path */ public Optional getNode(String...path) { return getNode(createTagArray(path)); } /** * Fetches a single {@link XmlNode}, located at the end of the path * specified by the given tag {@link String} arguments. *

* Each of the given path tokens may optionally contain an encoded index * (see {@link XmlTag#create(String)} for details). *

* If a token in the given path does not contain an index, and if it matches * several possible nodes, the first of those nodes is chosen. *

* Throws an {@link Exception} in case no node could be found at the given * path. * * @param path * one or several XML tag literals which describe the path to the * transitive child {@link XmlNode} to be found * @return the node found at the end of the given path (never null) * @throws XmlParserNodeNotFoundException * if no {@link XmlNode} could be identified at the given path, * or if an empty path was provided */ public XmlNode getNodeOrThrow(String...path) { return getNode(path).orElseThrow(XmlParserNodeNotFoundException::new); } /** * Fetches a single {@link XmlNode}, located at the end of the path * specified by the given {@link IXmlTag} instances. *

* Returns {@link Optional#empty()} in case no node could be found at the * given path. * * @param path * one or several {@link IXmlTag} instances which describe the * path to the transitive child node to be found (never * null) * @return the node found at the end of the given path */ public Optional getNode(IXmlTag...path) { return getNodeAtPath(this, 0, Arrays.asList(path)); } /** * Fetches a single {@link XmlNode}, located at the end of the path * specified by the given {@link IXmlTag} instances. *

* If there are several possible nodes for any token in the given path, the * first of those nodes is chosen. *

* Throws an {@link Exception} in case no node could be found at the given * path. * * @param path * one or several {@link IXmlTag} instances which describe the * path to the transitive child node to be found (never * null) * @return the node found at the end of the given path (never null) * @throws XmlParserNodeNotFoundException * if no {@link XmlNode} could be identified at the given path, * or if an empty path was provided */ public XmlNode getNodeOrThrow(IXmlTag...path) { return getNode(path).orElseThrow(XmlParserNodeNotFoundException::new); } // -------------------------------- miscellaneous -------------------------------- // /** * Recursively fetches all distinct tags that occur in the XML tree, * starting from this {@link XmlNode}. * * @return a {@link Set} of all distinct tags that occur in the XML tree * (never null) */ public Set getAllTags() { Set result = new TreeSet<>(); result.add(getTag()); for (XmlNode child: getChildren()) { result.addAll(child.getAllTags()); } return result; } @Override public String toString() { String output = new XmlNodePrinter().createSubTreeOutputString(this, getDepth()); if (output.indexOf("\n") == 0) { output = output.substring(1, output.length()); } return output; } void addChild(XmlNode child) { this.children.add(child); } private Optional getNodeAtPath(XmlNode startNode, int pathIndex, List path) { if (path != null && path.size() > 0) { IXmlTag indexedXmlTag = path.get(pathIndex); int tagIndex = indexedXmlTag.getIndex(); List childrenWithTag = startNode.getChildrenWithTag(indexedXmlTag); if (tagIndex < childrenWithTag.size()) { XmlNode node = childrenWithTag.get(tagIndex); if (pathIndex < path.size() - 1) { return getNodeAtPath(node, pathIndex + 1, path); } else { return Optional.of(node); } } } return Optional.empty(); } private XmlTag[] createTagArray(String...path) { return Arrays// .asList(path) .stream() .map(XmlTag::create) .collect(Collectors.toList()) .toArray(XmlTag[]::new); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy