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

com.mycila.xmltool.XMLDoc Maven / Gradle / Ivy

There is a newer version: 4.4.ga
Show newest version
/**
 * Copyright (C) 2008 Mycila ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mycila.xmltool;

import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;

import static com.mycila.xmltool.Utils.notEmpty;
import static com.mycila.xmltool.Utils.notNull;
import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE;

/**
 * @author Mathieu Carbou ([email protected])
 */
public final class XMLDoc implements XMLTag {

    private final XMLDocDefinition definition;
    Element current;

    XMLDoc(XMLDocDefinition definition) {
        this.definition = definition;
        this.current = definition.getRoot();
    }

    public NamespaceContext getContext() {
        return definition;
    }

    public boolean hasAttribute(String name) {
        return current.hasAttribute(name);
    }

    public boolean hasAttribute(String name, String relativeXpath, Object... arguments) {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).hasAttribute(name);
        }
        finally {
            current = old;
        }
    }

    public boolean hasTag(String relativeXpath, Object... arguments) {
        Element old = current;
        try {
            gotoTag(relativeXpath, arguments);
            return true;
        }
        catch (Exception e) {
            return false;
        }
        finally {
            current = old;
        }
    }

    public XMLTag forEachChild(CallBack callBack) {
        notNull("Callback", callBack);
        Element old = current;
        try {
            for (Element node : getChildElement()) {
                current = node;
                callBack.execute(this);
            }
            return this;
        }
        finally {
            current = old;
        }
    }

    public XMLTag forEach(CallBack callBack, String relativeXpath, Object... arguments) {
        notNull("Callback", callBack);
        Element old = current;
        try {
            Node[] nodes = definition.getXpath().findNodes(current, relativeXpath, arguments);
            List els = new ArrayList(nodes.length);
            for (Node node : nodes) {
                if (isElement(node)) {
                    els.add((Element) node);
                }
            }
            for (Element node : els) {
                current = node;
                callBack.execute(this);
            }
            return this;
        }
        finally {
            current = old;
        }
    }

    public XMLTag forEach(String xpath, CallBack callBack) {
        return forEach(callBack, xpath);
    }

    public String rawXpathString(String relativeXpath, Object... arguments) {
        return definition.getXpath().rawXpathString(current, relativeXpath, arguments);
    }

    public Number rawXpathNumber(String relativeXpath, Object... arguments) {
        return definition.getXpath().rawXpathNumber(current, relativeXpath, arguments);
    }

    public Boolean rawXpathBoolean(String relativeXpath, Object... arguments) {
        return definition.getXpath().rawXpathBoolean(current, relativeXpath, arguments);
    }

    public Node rawXpathNode(String relativeXpath, Object... arguments) {
        return definition.getXpath().rawXpathNode(current, relativeXpath, arguments);
    }

    public NodeList rawXpathNodeSet(String relativeXpath, Object... arguments) {
        return definition.getXpath().rawXpathNodeSet(current, relativeXpath, arguments);
    }

    public String getPefix(String namespaceURI) {
        notNull("namespaceURI", namespaceURI);
        String prefix = getContext().getPrefix(namespaceURI);
        return prefix == null ? XMLConstants.DEFAULT_NS_PREFIX : prefix;
    }

    @SuppressWarnings({"unchecked"})
    public String[] getPefixes(String namespaceURI) {
        notNull("namespaceURI", namespaceURI);
        Set prefixes = new TreeSet();
        Iterator i = getContext().getPrefixes(namespaceURI);
        while (i.hasNext()) {
            prefixes.add(i.next());
        }
        return prefixes.toArray(new String[prefixes.size()]);
    }

    public XMLTag addNamespace(String prefix, String namespaceURI) {
        definition.addNamespace(prefix, namespaceURI);
        return this;
    }

    public XMLTag addDocument(XMLTag tag) {
        notNull("XMLTag instance", tag);
        return addDocument(tag.toDocument());
    }

    public XMLTag addDocument(Document doc) {
        notNull("DOM Document", doc);
        current.appendChild(current.getOwnerDocument().importNode(doc.getDocumentElement(), true));
        return this;
    }

    public XMLTag addTag(XMLTag tag) {
        notNull("XMLTag instance", tag);
        return addTag(tag.getCurrentTag());
    }

    public XMLTag addTag(Element tag) {
        notNull("DOM Element", tag);
        current.appendChild(current.getOwnerDocument().importNode(tag, true));
        return this;
    }

    public XMLTag addTag(String name) {
        Element el = definition.createElement(name);
        current.appendChild(el);
        current = el;
        return this;
    }

    public XMLTag addAttribute(String name, String value) {
        if (hasAttribute(name)) {
            throw new XMLDocumentException("Attribute '%s' already exist on tag '%s'", name, getCurrentTagName());
        }
        definition.createAttribute(current, name, value);
        return this;
    }

    public XMLTag addAttribute(Attr attr) {
        notNull("DOM Attribute", attr);
        if (hasAttribute(attr.getName())) {
            throw new XMLDocumentException("Attribute '%s' already exist on tag '%s'", attr.getName(), getCurrentTagName());
        }
        current.setAttributeNodeNS((Attr) current.getOwnerDocument().importNode(attr, true));
        return this;
    }

    public XMLTag addText(String text) {
        current.appendChild(definition.createText(text));
        return gotoParent();
    }

    public XMLTag addText(Text text) {
        notNull("DOM Text node", text);
        current.appendChild(current.getOwnerDocument().importNode(text, true));
        return gotoParent();
    }

    public XMLTag addCDATA(String data) {
        current.appendChild(definition.createCDATA(data));
        return gotoParent();
    }

    public XMLTag addCDATA(CDATASection data) {
        notNull("DOM CDATA node", data);
        current.appendChild(current.getOwnerDocument().importNode(data, true));
        return gotoParent();
    }

    public XMLTag delete() {
        if (current == definition.getRoot()) {
            throw new XMLDocumentException("Cannot delete root node '%s'", getCurrentTagName());
        }
        Node toDelete = current;
        gotoParent();
        current.removeChild(toDelete);
        return this;
    }

    public XMLTag deleteChilds() {
        List toDelete = getChildElement();
        for (Element node : toDelete) {
            current.removeChild(node);
        }
        return this;
    }

    public XMLTag deleteAttributes() {
        List attrs = attr(current);
        for (Attr attr : attrs) {
            current.removeAttributeNode(attr);
        }
        return this;
    }

    public XMLTag deleteAttribute(String name) {
        notEmpty("Attribute name", name);
        if (!hasAttribute(name)) {
            throw new XMLDocumentException("Cannot delete attribute '%s' from element '%s': attribute does noe exist", name, getCurrentTagName());
        }
        current.removeAttribute(name);
        return this;
    }

    public XMLTag deleteAttributeIfExists(String name) {
        notEmpty("Attribute name", name);
        if (hasAttribute(name)) {
            current.removeAttribute(name);
        }
        return this;
    }

    public XMLTag renameTo(String newNodeName) {
        notEmpty("Tag name", newNodeName);
        current = definition.rename(current, newNodeName);
        return this;
    }

    public XMLTag deletePrefixes() {
        final boolean ignoreNS = definition.isIgnoreNamespaces();
        final String nsPref = XMLNS_ATTRIBUTE + ":";
        final Queue queue = new LinkedList();
        queue.offer(current);
        definition.resetNamespaces();
        while (!queue.isEmpty()) {
            Element tag = queue.poll();
            for (Attr attr : attr(tag)) {
                String attrName = attr.getNodeName();
                if (XMLNS_ATTRIBUTE.equals(attrName) || attrName.startsWith(nsPref)) {
                    tag.removeAttributeNode(attr);
                } else {
                    int pos = attrName.indexOf(":");
                    if (pos != -1) {
                        if (ignoreNS) {
                            definition.renameWithoutNS(attr, attrName.substring(pos + 1));
                        } else {
                            attr.setPrefix(null);
                        }
                    }
                }
            }
            String tagName = tag.getTagName();
            int pos = tagName.indexOf(":");
            if (pos != -1) {
                tagName = tagName.substring(pos + 1);
            }
            if (current == tag) {
                current = tag = definition.renameWithoutNS(tag, tagName);
            } else {
                tag = definition.renameWithoutNS(tag, tagName);
            }
            for (Element element : childs(tag)) {
                queue.offer(element);
            }
        }
        definition.readNamespaces();
        return this;
    }

    public XMLTag getInnerDocument() {
        return fromCurrentTag(this, definition.isIgnoreNamespaces());
    }

    public String getInnerText() {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.ENCODING, definition.getEncoding());
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter sw = new StringWriter();
            NodeList list = current.getChildNodes();
            for (int i = 0; i < list.getLength(); i++) {
                transformer.transform(new DOMSource(list.item(i)), new StreamResult(sw));
            }
            return sw.toString();
        }
        catch (TransformerException e) {
            throw new XMLDocumentException("Transformation error", e);
        }

    }

    public XMLTag gotoParent() {
        Node n = current.getParentNode();
        if (current != definition.getRoot() && isElement(n)) {
            current = (Element) n;
        }
        return this;
    }

    public XMLTag gotoRoot() {
        current = definition.getRoot();
        return this;
    }

    public XMLTag gotoChild() {
        List els = childs(current);
        switch (els.size()) {
            case 0:
                throw new XMLDocumentException("Current element '%s' has no child", getCurrentTagName());
            case 1:
                current = els.get(0);
                break;
            default:
                throw new XMLDocumentException("Cannot select child: current element '%s' has '%s' children", getCurrentTagName(), els.size());
        }
        return this;
    }

    public XMLTag gotoChild(int i) {
        List els = childs(current);
        if (i > 0 && i <= els.size()) {
            current = els.get(i - 1);
        } else {
            throw new XMLDocumentException("Cannot acces child '%s' of element '%s' amongst its '%s' childs", i, getCurrentTagName(), els.size());
        }
        return this;
    }

    public XMLTag gotoChild(String nodeName) {
        notEmpty("Tag name", nodeName);
        List els = childs(current);
        List found = new ArrayList(els.size());
        for (Element el : els) {
            if (el.getTagName().equals(nodeName)) {
                found.add(el);
            }
        }
        switch (found.size()) {
            case 0:
                throw new XMLDocumentException("Current element '%s' has no child named '%s'", getCurrentTagName(), nodeName);
            case 1:
                current = found.get(0);
                break;
            default:
                throw new XMLDocumentException("Cannot select child: current element '%s' has '%s' children named '%s'", getCurrentTagName(), found.size(), nodeName);
        }
        return this;
    }

    public XMLTag gotoFirstChild() throws XMLDocumentException {
        List els = childs(current);
        if (els.isEmpty()) {
            throw new XMLDocumentException("Current element '%s' has no child", getCurrentTagName());
        }
        current = els.get(0);
        return this;
    }

    public XMLTag gotoFirstChild(String name) throws XMLDocumentException {
        notEmpty("Tag name", name);
        List els = childs(current);
        if (els.isEmpty()) {
            throw new XMLDocumentException("Current element '%s' has no child", getCurrentTagName());
        }
        for (Element el : els) {
            if (el.getTagName().equals(name)) {
                current = el;
                return this;
            }
        }
        throw new XMLDocumentException("No child found in current tag '%s' having name '%s'", getCurrentTagName(), name);
    }

    public XMLTag gotoLastChild() throws XMLDocumentException {
        List els = childs(current);
        if (els.isEmpty()) {
            throw new XMLDocumentException("Current element '%s' has no child", getCurrentTagName());
        }
        current = els.get(els.size() - 1);
        return this;
    }

    public XMLTag gotoLastChild(String name) throws XMLDocumentException {
        notEmpty("Tag name", name);
        List els = childs(current);
        if (els.isEmpty()) {
            throw new XMLDocumentException("Current element '%s' has no child", getCurrentTagName());
        }
        for (int i = els.size() - 1; i >= 0; i--) {
            if (els.get(i).getTagName().equals(name)) {
                current = els.get(i);
                return this;
            }
        }
        throw new XMLDocumentException("No child found in current tag '%s' having name '%s'", getCurrentTagName(), name);
    }

    public XMLTag gotoTag(String relativeXpath, Object... arguments) {
        Node n = definition.getXpath().findNode(current, relativeXpath, arguments);
        if (!isElement(n)) {
            throw new XMLDocumentException("XPath expression '%s' does not target an element. Targeted node is '%s' (node type is '%s')", String.format(relativeXpath, arguments), n.getNodeName(), n.getNodeType());
        }
        current = (Element) n;
        return this;
    }

    public Element getCurrentTag() {
        return current;
    }

    public int getChildCount() {
        return getChildElement().size();
    }

    public Iterable getChilds() {
        final IteratorAdapter iterator = new IteratorAdapter(this, getChildElement().iterator());
        return new Iterable() {
            public Iterator iterator() {
                return iterator;
            }
        };
    }

    public Iterable getChilds(String relativeXpath, Object... arguments) {
        Node[] nodes = definition.getXpath().findNodes(current, relativeXpath, arguments);
        List els = new ArrayList(nodes.length);
        for (Node node : nodes) {
            if (isElement(node)) {
                els.add((Element) node);
            }
        }
        final IteratorAdapter iterator = new IteratorAdapter(this, els.iterator());
        return new Iterable() {
            public Iterator iterator() {
                return iterator;
            }
        };
    }

    public List getChildElement() {
        return childs(current);
    }

    public String getCurrentTagName() {
        return current.getTagName();
    }

    public String getCurrentTagLocation() {
        StringBuilder sb = new StringBuilder();
        Element thisNode = current;
        while (thisNode != definition.getRoot()) {
            Element parent = (Element) thisNode.getParentNode();
            List els = childs(parent);
            for (int i = 0; i < els.size(); i++) {
                if (els.get(i) == thisNode) {
                    sb.insert(0, "/*[" + (i + 1) + "]");
                    break;
                }
            }
            thisNode = parent;
        }
        return sb.length() == 0 ? "." : sb.deleteCharAt(0).toString();
    }

    public String getAttribute(String name) {
        notEmpty("Attribute name", name);
        if (!hasAttribute(name)) {
            throw new XMLDocumentException("Element '%s' does not have attribute '%s'", getCurrentTagName(), name);
        }
        return current.getAttribute(name);
    }

    public String findAttribute(String name) {
        notEmpty("Attribute name", name);
        return hasAttribute(name) ? current.getAttribute(name) : null;
    }

    public String getAttribute(String name, String relativeXpath, Object... arguments) {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).getAttribute(name);
        }
        finally {
            current = old;
        }
    }

    public String findAttribute(String name, String relativeXpath, Object... arguments) throws XMLDocumentException {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).findAttribute(name);
        }
        finally {
            current = old;
        }
    }

    @SuppressWarnings({"MismatchedReadAndWriteOfArray"})
    public String[] getAttributeNames() {
        List attrs = attr(current);
        String[] names = new String[attrs.size()];
        for (int i = 0; i < attrs.size(); i++) {
            names[i] = (attrs.get(i)).getName();
        }
        return names;
    }

    public String getText(String relativeXpath, Object... arguments) {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).getText();
        }
        finally {
            current = old;
        }
    }

    public String getText() {
        StringBuilder sb = new StringBuilder();
        List nodes = childs(Document.TEXT_NODE);
        for (Node node : nodes) {
            String val = node.getNodeValue();
            if (val != null) {
                sb.append(val);
            }
        }
        return sb.toString();
    }

    public String getTextOrCDATA() {
        String txt = getText();
        return "".equals(txt) ? getCDATA() : txt;

    }

    public String getTextOrCDATA(String relativeXpath, Object... arguments) throws XMLDocumentException {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).getTextOrCDATA();
        }
        finally {
            current = old;
        }
    }

    public String getCDATAorText() {
        String txt = getCDATA();
        return "".equals(txt) ? getText() : txt;
    }

    public String getCDATAorText(String relativeXpath, Object... arguments) throws XMLDocumentException {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).getCDATAorText();
        }
        finally {
            current = old;
        }
    }

    public String getCDATA(String relativeXpath, Object... arguments) {
        Element old = current;
        try {
            return gotoTag(relativeXpath, arguments).getCDATA();
        }
        finally {
            current = old;
        }
    }

    public String getCDATA() {
        StringBuilder sb = new StringBuilder();
        List nodes = childs(Document.CDATA_SECTION_NODE);
        for (Node node : nodes) {
            String val = ((CDATASection) node).getData();
            if (val != null) {
                sb.append(val);
            }
        }
        return sb.toString();
    }

    public Document toDocument() {
        return definition.getDocument();
    }

    public Source toSource() {
        return new DOMSource(toDocument());
    }

    @Override
    public String toString() {
        return toString(definition.getEncoding());
    }

    public String toString(String encoding) {
        StringWriter out = new StringWriter();
        toStream(out, encoding);
        return out.toString();
    }

    public byte[] toBytes() {
        return toBytes(definition.getEncoding());
    }

    public byte[] toBytes(String encoding) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        toStream(out, encoding);
        return out.toByteArray();
    }

    public XMLTag toStream(OutputStream out) {
        return toStream(out, definition.getEncoding());
    }

    public XMLTag toStream(OutputStream out, String encoding) {
        notEmpty("encoding", encoding);
        try {
            return toStream(new BufferedWriter(new OutputStreamWriter(out, encoding)));
        } catch (UnsupportedEncodingException e) {
            throw new XMLDocumentException(e.getMessage(), e);
        }
    }

    public XMLTag toStream(Writer out) {
        return toStream(out, definition.getEncoding());
    }

    public XMLTag toStream(Writer out, String encoding) {
        notEmpty("encoding", encoding);
        return toResult(new StreamResult(out), encoding);
    }

    public Result toResult() {
        Result r = new DOMResult();
        toResult(r);
        return r;
    }

    public Result toResult(String encoding) {
        Result r = new DOMResult();
        toResult(r, encoding);
        return r;
    }

    public OutputStream toOutputStream() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        toStream(baos);
        return baos;
    }

    public OutputStream toOutputStream(String encoding) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        toStream(baos, encoding);
        return baos;
    }

    public Writer toWriter() {
        Writer w = new StringWriter();
        toStream(w);
        return w;
    }

    public Writer toWriter(String encoding) {
        Writer w = new StringWriter();
        toStream(w, encoding);
        return w;
    }

    public XMLTag toResult(Result out) {
        return toResult(out, definition.getEncoding());
    }

    public XMLTag toResult(Result out, String encoding) {
        notEmpty("encoding", encoding);
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            try {
                tf.setAttribute("indent-number", 4);
            } catch (Exception ignored) {
            }
            Transformer transformer = tf.newTransformer();
            transformer.setParameter("indent-number", 4);
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.STANDALONE, definition.getDocument().getXmlStandalone() ? "yes" : "no");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            transformer.transform(toSource(), out);
            return this;
        }
        catch (TransformerException e) {
            throw new XMLDocumentException("Transformation error", e);
        }
    }

    public ValidationResult validate(Source... schemas) {
        notNull("schemas", schemas);
        try {
            return Utils.validate(this.toDocument(), schemas);
        }
        catch (Exception e) {
            throw new XMLDocumentException("Validation failed", e);
        }
    }

    public ValidationResult validate(URL... schemaLocations) {
        notNull("schemaLocations", schemaLocations);
        try {
            return Utils.validate(this.toDocument(), schemaLocations);
        }
        catch (Exception e) {
            throw new XMLDocumentException("Validation failed", e);
        }
    }

    private boolean isElement(Node n) {
        return n != null && n.getNodeType() == Document.ELEMENT_NODE;
    }

    private List childs(Element e) {
        NodeList list = e.getChildNodes();
        List els = new ArrayList(list.getLength());
        for (int i = 0; i < list.getLength(); i++) {
            if (isElement(list.item(i))) {
                els.add((Element) list.item(i));
            }
        }
        return els;
    }

    private List attr(Element e) {
        NamedNodeMap list = e.getAttributes();
        List attrs = new ArrayList(list.getLength());
        for (int i = 0; i < list.getLength(); i++) {
            attrs.add((Attr) list.item(i));
        }
        return attrs;
    }

    private List childs(short type) {
        NodeList childs = current.getChildNodes();
        List nodes = new ArrayList(childs.getLength());
        for (int i = 0; i < childs.getLength(); i++) {
            if (childs.item(i).getNodeType() == type) {
                nodes.add(childs.item(i));
            }
        }
        return nodes;
    }

    public XMLTag duplicate() {
        return XMLDoc.from(this, definition.isIgnoreNamespaces())
                .gotoRoot()
                .gotoTag(getCurrentTagLocation());
    }

    public XMLTag setText(String text) {
        for (Node node : childs(Document.CDATA_SECTION_NODE)) {
            current.removeChild(node);
        }
        for (Node node : childs(Document.TEXT_NODE)) {
            current.removeChild(node);
        }
        return addText(text);
    }

    public XMLTag setText(String text, String relativeXpath, Object... arguments) throws XMLDocumentException {
        Element old = current;
        try {
            gotoTag(relativeXpath, arguments).setText(text);
        }
        finally {
            current = old;
        }
        return this;
    }

    public XMLTag setTextIfExist(String text, String relativeXpath, Object... arguments) throws XMLDocumentException {
        return hasTag(relativeXpath, arguments) ? setText(text, relativeXpath, arguments) : this;
    }

    public XMLTag setCDATA(String data) {
        for (Node node : childs(Document.CDATA_SECTION_NODE)) {
            current.removeChild(node);
        }
        for (Node node : childs(Document.TEXT_NODE)) {
            current.removeChild(node);
        }
        return addCDATA(data);
    }

    public XMLTag setCDATA(String data, String relativeXpath, Object... arguments) throws XMLDocumentException {
        Element old = current;
        try {
            gotoTag(relativeXpath, arguments).setCDATA(data);
        }
        finally {
            current = old;
        }
        return this;
    }

    public XMLTag setCDATAIfExist(String data, String relativeXpath, Object... arguments) throws XMLDocumentException {
        return hasTag(relativeXpath, arguments) ? setCDATA(data, relativeXpath, arguments) : this;
    }

    public XMLTag setAttribute(String name, String value) throws XMLDocumentException {
        notNull("Attribute name", name);
        notNull("Attribute value", value);
        if (!hasAttribute(name)) {
            throw new XMLDocumentException("Element '%s' does not have attribute '%s'", getCurrentTagName(), name);
        }
        current.getAttributeNode(name).setValue(value);
        return this;
    }

    public XMLTag setAttributeIfExist(String name, String value) {
        notNull("Attribute name", name);
        notNull("Attribute value", value);
        if (hasAttribute(name)) {
            current.getAttributeNode(name).setValue(value);
        }
        return this;
    }

    public XMLTag setAttribute(String name, String value, String relativeXpath, Object... arguments) throws XMLDocumentException {
        Element old = current;
        try {
            gotoTag(relativeXpath, arguments).setAttribute(name, value);
        }
        finally {
            current = old;
        }
        return this;
    }

    public XMLTag setAttributeIfExist(String name, String value, String relativeXpath, Object... arguments) throws XMLDocumentException {
        return hasAttribute(name, relativeXpath, arguments) ? setAttribute(name, value, relativeXpath, arguments) : this;
    }

    public static XMLDocBuilder newDocument(boolean ignoreNamespaces) {
        return XMLDocBuilder.newDocument(ignoreNamespaces);
    }

    public static XMLTag from(Node node, boolean ignoreNamespaces) {
        notNull("Node", node);
        return XMLDocBuilder.from(node, ignoreNamespaces);
    }

    public static XMLTag from(InputSource source, boolean ignoreNamespaces) {
        notNull("InputSource", source);
        return XMLDocBuilder.from(source, ignoreNamespaces);
    }

    public static XMLTag from(Reader reader, boolean ignoreNamespaces) {
        notNull("Reader", reader);
        return XMLDocBuilder.from(reader, ignoreNamespaces);
    }

    public static XMLTag from(InputStream is, boolean ignoreNamespaces) {
        notNull("InputStream", is);
        return XMLDocBuilder.from(is, ignoreNamespaces);
    }

    public static XMLTag from(File file, boolean ignoreNamespaces) {
        notNull("File", file);
        return XMLDocBuilder.from(file, ignoreNamespaces);
    }

    public static XMLTag from(URL xmlLocation, boolean ignoreNamespaces) {
        notNull("URL", xmlLocation);
        return XMLDocBuilder.from(xmlLocation, ignoreNamespaces);
    }

    public static XMLTag from(String xmlData, boolean ignoreNamespaces) {
        notEmpty("XML Data", xmlData);
        return XMLDocBuilder.from(xmlData, ignoreNamespaces);
    }

    public static XMLTag from(Source source, boolean ignoreNamespaces) {
        notNull("Source", source);
        return XMLDocBuilder.from(source, ignoreNamespaces);
    }

    public static XMLTag from(XMLTag tag, boolean ignoreNamespaces) {
        notNull("XML Tag", tag);
        return XMLDocBuilder.from(tag, ignoreNamespaces);
    }

    public static XMLDocBuilder newDocument() {
        return newDocument(true);
    }

    public static XMLTag from(Node node) {
        return from(node, true);
    }

    public static XMLTag from(InputSource source) {
        return from(source, true);
    }

    public static XMLTag from(Reader reader) {
        return from(reader, true);
    }

    public static XMLTag from(InputStream is) {
        return from(is, true);
    }

    public static XMLTag from(File file) {
        return from(file, true);
    }

    public static XMLTag from(URL xmlLocation) {
        return from(xmlLocation, true);
    }

    public static XMLTag from(String xmlData) {
        return from(xmlData, true);
    }

    public static XMLTag from(Source source) {
        return from(source, true);
    }

    public static XMLTag from(XMLTag tag) {
        return from(tag, true);
    }

    /**
     * Create another {@link com.mycila.xmltool.XMLTag} instance from the hierarchy under the current tag. The current tag becomes the root tag.
     *
     * @param tag              The current XML Tag positionned to the new root tag
     * @param ignoreNamespaces Wheter to build a namespace aware document
     * @return The inner XMLTag instance
     */
    public static XMLTag fromCurrentTag(XMLTag tag, boolean ignoreNamespaces) {
        notNull("XML Tag", tag);
        return XMLDocBuilder.fromCurrentTag(tag, ignoreNamespaces);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy