/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.commons.xml;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import static com.google.common.io.Files.toByteArray;
import static java.nio.file.Files.delete;
import static java.nio.file.Files.exists;
import static java.nio.file.Files.newOutputStream;
import static java.nio.file.Files.readAllBytes;
import static java.nio.file.Files.write;
import static java.util.Arrays.asList;
import static org.eclipse.che.commons.xml.XMLTreeLocation.after;
import static org.eclipse.che.commons.xml.XMLTreeLocation.before;
import static org.eclipse.che.commons.xml.XMLTreeLocation.inTheBegin;
import static org.eclipse.che.commons.xml.XMLTreeLocation.inTheEnd;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* @author Eugene Voevodin
*/
public class XMLTreeTest {
private static final String XML_CONTENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <parent>\n" +
" <artifactId>test-parent</artifactId>\n" +
" <groupId>test-parent-group-id</groupId>\n" +
" <version>test-parent-version</version>\n" +
" </parent>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <name>Test</name>\n" +
" <configuration>\n" +
" <items combine.children=\"append\">\n" +
" <item>parent-1</item>\n" +
" <item>parent-2</item>\n" +
" <item>child-1</item>\n" +
" </items>\n" +
" <properties combine.self=\"override\">\n" +
" <childKey>child</childKey>\n" +
" </properties>\n" +
" </configuration>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <groupId>com.google.guava</groupId>\n" +
" <artifactId>guava</artifactId>\n" +
" <version>18.0</version>\n" +
" </dependency>\n" +
" <!-- Test dependencies -->\n" +
" <dependency>\n" +
" <groupId>org.testng</groupId>\n" +
" <artifactId>testng</artifactId>\n" +
" <version>6.8</version>\n" +
" <scope>test</scope>\n" +
" </dependency>\n" +
" <dependency>\n" +
" <groupId>org.mockito</groupId>\n" +
" <artifactId>mockito-core</artifactId>\n" +
" <version>1.10.0</version>\n" +
" <scope>test</scope>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>\n";
@BeforeMethod
private void resetLineSeparator() {
System.setProperty("line.separator", "\n");
}
@Test(expectedExceptions = XMLTreeException.class)
public void shouldThrowExceptionWhenXMLContentContainsDoctypeDeclaration() throws Exception {
String xml = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE lolz [\n" +
"<!ENTITY lol \"lol\">\n" +
"<!ENTITY lol2 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
"<!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
"<!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
"<!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
"<!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
"<!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
"<!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
"<!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
"]>\n" +
"<lolz>&lol9;</lolz>";
XMLTree.from(xml);
}
@Test
public void shouldFindSingleText() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final String version = tree.getSingleText("/project/dependencies/dependency[groupId='org.testng']/version");
assertEquals(version, "6.8");
}
@Test
public void shouldFindEachElementText() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final List<String> artifacts = tree.getText("/project/dependencies/dependency[scope='test']/artifactId");
assertEquals(artifacts, asList("testng", "mockito-core"));
}
@Test
public void shouldFindElements() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final List<Element> artifacts = tree.getElements("/project/dependencies/dependency[scope='test']/artifactId");
assertEquals(artifacts.size(), 2);
assertEquals(asList(artifacts.get(0).getText(), artifacts.get(1).getText()), asList("testng", "mockito-core"));
}
@Test
public void shouldFindAttributeValues() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final List<String> attributes = tree.getText("/project/configuration/properties/@combine.self");
assertEquals(attributes, asList("override"));
}
@Test
public void shouldBeAbleToGetAttributesUsingModel() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element properties = tree.getSingleElement("/project/configuration/properties");
assertEquals(properties.getAttributes().size(), 1);
final Attribute attribute = properties.getAttributes().get(0);
assertEquals(attribute.getName(), "combine.self");
assertEquals(attribute.getValue(), "override");
}
@Test
public void shouldBeAbleToGetElementParent() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element artifactId = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']/artifactId");
assertEquals(artifactId.getParent().getName(), "dependency");
}
@Test
public void shouldBeAbleToGetSingleSibling() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element name = tree.getSingleElement("/project/name");
assertEquals(name.getSingleSibling("packaging").getText(), "jar");
}
@Test
public void shouldReturnNullIfSiblingWithRequestedNameDoesNotExist() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element name = tree.getSingleElement("/project/name");
assertNull(name.getSingleSibling("developers"));
}
@Test
public void shouldBeAbleToCheckThatElementHasAttribute() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
assertTrue(tree.getSingleElement("//properties").hasAttribute("combine.self"));
}
@Test(expectedExceptions = XMLTreeException.class)
public void shouldThrowExceptionIfMoreThenOnlySiblingWereFound() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element dependency = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
dependency.getSingleSibling("dependency");
}
@Test
public void shouldBeAbleToGetOnlyChild() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
assertEquals(tree.getRoot().getSingleChild("packaging").getText(), "jar");
}
@Test
public void shouldReturnNullIfChildDoesNotExist() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
assertNull(tree.getRoot().getSingleChild("developers"));
}
@Test(expectedExceptions = XMLTreeException.class)
public void shouldThrowExceptionIfMoreThenOnlyChildWereFound() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element dependencies = tree.getSingleElement("/project/dependencies");
dependencies.getSingleChild("dependency");
}
@Test
public void shouldBeAbleToCheckElementHasSibling() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element artifactID = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']/artifactId");
assertTrue(artifactID.hasSibling("groupId"));
assertTrue(artifactID.hasSibling("version"));
assertTrue(artifactID.hasSibling("scope"));
assertFalse(artifactID.hasSibling("artifactId"));
}
@Test
public void shouldBeAbleToGetSibling() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element artifactId = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']/artifactId");
assertEquals(artifactId.getSingleSibling("groupId").getText(), "org.testng");
assertEquals(artifactId.getSingleSibling("version").getText(), "6.8");
assertEquals(artifactId.getSingleSibling("scope").getText(), "test");
assertNull(artifactId.getSingleSibling("other"));
}
@Test
public void shouldBeAbleToGetPreviousSibling() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element scope = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']/scope");
assertEquals(scope.getPreviousSibling().getName(), "version");
}
@Test
public void shouldBeAbleToGetChildText() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final String artifactId = tree.getRoot().getChildText("artifactId");
assertEquals(artifactId, "test-artifact");
}
@Test
public void shouldReturnNullWhenGettingTextIfChildDoesNotExist() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element dependency = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
assertNull(dependency.getChildText("scope"));
}
@Test
public void shouldBeAbleToGetChildTextOrDefaultValue() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element dependency = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
assertEquals(dependency.getChildTextOrDefault("scope", "compile"), "compile");
}
@Test
public void shouldBeAbleToGetNextSibling() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element scope = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']/version");
assertEquals(scope.getNextSibling().getName(), "scope");
}
@Test
public void shouldBeAbleToGetRootElement() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element project = tree.getRoot();
assertEquals(project.getName(), "project");
assertFalse(project.hasParent());
}
@Test
public void shouldBeAbleToGetSiblings() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element artifactId = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']/artifactId");
assertEquals(artifactId.getSiblings().size(), 3);
}
@Test
public void shouldBeAbleToCheckElementHasChild() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element guavaDep = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
assertTrue(guavaDep.hasChild("groupId"));
assertTrue(guavaDep.hasChild("version"));
assertTrue(guavaDep.hasChild("artifactId"));
assertFalse(guavaDep.hasChild("scope"));
}
@Test
public void shouldBeAbleToGetFirstChild() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element guavaDep = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
assertEquals(guavaDep.getSingleChild("groupId").getText(), "com.google.guava");
assertEquals(guavaDep.getSingleChild("version").getText(), "18.0");
assertEquals(guavaDep.getSingleChild("artifactId").getText(), "guava");
assertNull(guavaDep.getSingleChild("scope"));
}
@Test
public void shouldBeAbleToGetChildren() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element guavaDep = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
assertEquals(guavaDep.getChildren().size(), 3);
}
@Test
public void shouldBeAbleToChangeElementTextByModel() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element name = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']/version");
name.setText("new version");
assertEquals(tree.getSingleText("/project/dependencies/dependency[artifactId='guava']/version"), "new version");
}
@Test
public void shouldBeAbleToChangeElementTextByTree() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
tree.updateText("/project/name", "new name");
assertEquals(tree.getSingleText("/project/name"), "new name");
}
@Test
public void shouldBeAbleToAppendChildByModel() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element guavaDep = tree.getSingleElement("/project/dependencies/dependency[artifactId='guava']");
guavaDep.appendChild(NewElement.createElement("scope", "compile"));
assertTrue(guavaDep.hasChild("scope"));
assertEquals(guavaDep.getSingleChild("scope").getText(), "compile");
assertEquals(tree.getSingleText("/project/dependencies/dependency[artifactId='guava']/scope"), "compile");
}
@Test
public void shouldBeAbleToAppendComplexChild() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
tree.getSingleElement("//dependencies")
.appendChild(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")));
final Element dependency = tree.getSingleElement("//dependency[artifactId='test-artifact']");
assertTrue(dependency.hasChild("artifactId"));
assertTrue(dependency.hasChild("groupId"));
assertTrue(dependency.hasChild("version"));
}
@Test
public void shouldBeAbleToInsertElementAfterExisting() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element name = tree.getSingleElement("/project/name");
name.insertAfter(NewElement.createElement("description", "This is test pom.xml"));
assertTrue(name.hasSibling("description"));
assertEquals(name.getNextSibling().getText(), "This is test pom.xml");
assertEquals(tree.getSingleText("/project/description"), "This is test pom.xml");
}
@Test
public void shouldBeAbleToInsertElementBeforeExisting() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element name = tree.getSingleElement("/project/name");
name.insertBefore(NewElement.createElement("description", "This is test pom.xml"));
assertTrue(name.hasSibling("description"));
assertEquals(name.getPreviousSibling().getText(), "This is test pom.xml");
assertEquals(tree.getSingleText("/project/description"), "This is test pom.xml");
}
@Test
public void shouldBeAbleToInsertChildAfterSpecifiedElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.getRoot()
.insertChild(NewElement.createElement("packaging", "jar"), after("artifactId"));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
}
@Test
public void shouldBeAbleToInsertChildBeforeSpecifiedElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.getRoot()
.insertChild(NewElement.createElement("modelVersion", "4.0.0"), before("artifactId"));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
}
@Test
public void shouldBeAbleToInsertChildInTheStartOfChildrenList() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.getRoot()
.insertChild(NewElement.createElement("modelVersion", "4.0.0"), before("artifactId").or(inTheBegin()));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
}
@Test
public void shouldBeAbleToInsertChildInTheEndOfChildrenList() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <name>Test</name>\n" +
"</project>");
tree.getRoot()
.insertChild(NewElement.createElement("groupId", "test-group-id"), after("artifactId").or(inTheEnd()));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <name>Test</name>\n" +
" <groupId>test-group-id</groupId>\n" +
"</project>");
}
@Test(expectedExceptions = XMLTreeException.class)
public void shouldThrowExceptionIfNotPossibleToInsertElementInSpecifiedPlace() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <name>Test</name>\n" +
"</project>");
tree.getRoot()
.insertChild(NewElement.createElement("groupId", "test-group-id"), after("artifactId").or(after("version"))
.or(after("parent"))
.or(after("build")));
}
@Test
public void shouldBeAbleToReplaceElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <dependencies>\n" +
" <!-- Test dependencies -->\n" +
" <dependency>\n" +
" <groupId>org.testng</groupId>\n" +
" <artifactId>testng</artifactId>\n" +
" <version>6.8</version>\n" +
" <scope>test</scope>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>\n");
tree.getSingleElement("//dependency")
.replaceWith(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "junit"),
NewElement.createElement("groupId", "org.junit"),
NewElement.createElement("version", "4.0")));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <dependencies>\n" +
" <!-- Test dependencies -->\n" +
" <dependency>\n" +
" <artifactId>junit</artifactId>\n" +
" <groupId>org.junit</groupId>\n" +
" <version>4.0</version>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>\n");
assertEquals(tree.getElements("//dependency").size(), 1);
assertEquals(tree.getSingleElement("//dependencies").getChildren().size(), 1);
}
@Test
public void shouldBeAbleToInsertElementBeforeFirstExisting() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element modelVersion = tree.getSingleElement("/project/modelVersion");
modelVersion.insertBefore(NewElement.createElement("description", "This is test pom.xml"));
assertTrue(modelVersion.hasSibling("description"));
assertEquals(modelVersion.getPreviousSibling().getText(), "This is test pom.xml");
assertEquals(tree.getSingleText("/project/description"), "This is test pom.xml");
}
@Test
public void shouldBeAbleToRemoveElementByTree() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
assertTrue(tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']").hasChild("scope"));
tree.removeElement("/project/dependencies/dependency[artifactId='testng']/scope");
assertFalse(tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']").hasChild("scope"));
}
@Test
public void shouldBeAbleToRemoveElementChild() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element dependency = tree.getSingleElement("/project/dependencies/dependency[artifactId='testng']");
assertTrue(dependency.hasChild("version"));
dependency.removeChild("version");
assertFalse(dependency.hasChild("version"));
}
@Test
public void shouldBeAbleToRemoveChildren() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element dependencies = tree.getSingleElement("/project/dependencies");
dependencies.removeChildren("dependency");
assertTrue(dependencies.getChildren().isEmpty());
}
@Test
public void newElementWithPostAddedChildrenAndNewElementConstructedWithChildrenShouldProduceSameTreeBytes() {
final XMLTree tree1 = XMLTree.from(XML_CONTENT);
final XMLTree tree2 = XMLTree.from(XML_CONTENT);
//first tree
tree1.getSingleElement("//dependencies")
.appendChild(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")));
//second tree
final NewElement dependency = NewElement
.createElement("dependency").appendChild(NewElement.createElement("artifactId", "test-artifact"))
.appendChild(NewElement.createElement("groupId", "test-group"))
.appendChild(NewElement.createElement("version", "test-version"));
tree2.getSingleElement("//dependencies")
.appendChild(dependency);
assertEquals(tree2.toString(), tree1.toString());
}
@Test
public void chainRemovingAndBatchRemovingShouldProduceSameTreeBytes() {
final XMLTree tree1 = XMLTree.from(XML_CONTENT);
final XMLTree tree2 = XMLTree.from(XML_CONTENT);
//removing dependencies from first tree
tree1.removeElement("/project/dependencies/dependency[3]");
tree1.removeElement("/project/dependencies/dependency[2]");
tree1.removeElement("/project/dependencies/dependency[1]");
//removing dependencies from second tree
tree2.getSingleElement("//dependencies").removeChildren("dependency");
//use strings for assertion to quick review difference if assertion failed
assertEquals(tree1.toString(), tree2.toString());
}
@Test
public void removeInsertedElementShouldProduceSameTreeBytes() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element description = tree.getRoot()
.getLastChild()
.insertAfter(NewElement.createElement("description", "description"))
.getSingleSibling("description");
description.remove();
assertEquals(tree.toString(), XML_CONTENT);
}
@Test
public void removeInsertedAfterElementWithChildrenShouldProduceSameTreeBytes() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
tree.getSingleElement("//dependencies")
.getFirstChild()
.insertAfter(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")))
.getNextSibling()
.remove();
assertEquals(tree.toString(), XML_CONTENT);
}
@Test
public void removeAppendedElementWithChildrenShouldProduceSameTreeBytes() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
tree.getSingleElement("//dependencies")
.appendChild(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")))
.getLastChild()
.remove();
//use strings for assertion to quick review difference if assertion failed
assertEquals(tree.toString(), XML_CONTENT);
}
@Test
public void removeInsertedBeforeElementWithChildrenShouldProduceSameTreeBytes() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
tree.getSingleElement("//dependencies")
.getFirstChild()
.insertBefore(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")))
.getPreviousSibling()
.remove();
//use strings for assertion to quick review difference if assertion failed
assertEquals(tree.toString(), XML_CONTENT);
}
@Test
public void shouldBeAbleToChangeTextOfNewlyInsertedElement() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
tree.getSingleElement("//dependencies")
.getFirstChild()
.insertBefore(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")));
tree.updateText("//dependencies/dependency[artifactId='test-artifact']/version", "test-version");
assertEquals(tree.getSingleText("//dependencies/dependency[artifactId='test-artifact']/version"), "test-version");
}
@Test
public void shouldBeAbleToChangeInsertedElementText() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.getRoot()
.getLastChild()
.insertBefore(NewElement.createElement("description", "description"))
.getPreviousSibling()
.setText("other description");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <description>other description</description>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
}
@Test
public void shouldBeAbleToRemoveAttribute() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>\n" +
" <level1 attribute=\"value\">text</level1>\n" +
"</root>");
tree.getSingleElement("//level1")
.removeAttribute("attribute");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>\n" +
" <level1>text</level1>\n" +
"</root>");
}
@Test
public void shouldBeAbleToChangeAttributeValue() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>\n" +
" <level1 longer=\"value\" long=\"value\">text</level1>\n" +
"</root>");
tree.getSingleElement("//level1")
.getAttribute("long")
.setValue("new value");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>\n" +
" <level1 longer=\"value\" long=\"new value\">text</level1>\n" +
"</root>");
}
@Test
public void shouldBeAbleToAddAttributeToExistingElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project></project>");
tree.getRoot().setAttribute("xlmns", "http://maven.apache.org/POM/4.0.0");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xlmns=\"http://maven.apache.org/POM/4.0.0\"></project>");
}
@Test
public void shouldBeAbleToAddAttributesWithPrefix() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project></project>");
tree.getRoot()
.setAttribute("xmlns", "http://maven.apache.org/POM/4.0.0")
.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
.setAttribute("xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd");
tree.getRoot().getAttributes();
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\"></project>");
assertEquals(tree.getRoot()
.getAttributes()
.size(), 3);
//xmlns
assertTrue(tree.getRoot().hasAttribute("xmlns"));
final Attribute xmlns = tree.getRoot().getAttribute("xmlns");
assertEquals(xmlns.getValue(), "http://maven.apache.org/POM/4.0.0");
//xmlns:xsi
assertTrue(tree.getRoot().hasAttribute("xmlns:xsi"));
final Attribute xmlnsXsi = tree.getRoot().getAttribute("xmlns:xsi");
assertEquals(xmlnsXsi.getValue(), "http://www.w3.org/2001/XMLSchema-instance");
assertEquals(xmlnsXsi.getPrefix(), "xmlns");
//xsi:schemaLocation
assertTrue(tree.getRoot().hasAttribute("xsi:schemaLocation"));
final Attribute xsiSchemaLocation = tree.getRoot().getAttribute("xsi:schemaLocation");
assertEquals(xsiSchemaLocation.getValue(), "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd");
assertEquals(xsiSchemaLocation.getPrefix(), "xsi");
}
@Test
public void shouldBeAbleToAddAttributeToNewElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" </dependencies>\n" +
"</project>");
tree.getSingleElement("//dependencies")
.appendChild(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version").setAttribute("attribute1", "value1"))
.setAttribute("attribute1", "value1")
.setAttribute("attribute2", "value2")
.setAttribute("attribute3", "value3"));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency attribute1=\"value1\" attribute2=\"value2\" attribute3=\"value3\">\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version attribute1=\"value1\">test-version</version>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>");
}
@Test
public void shouldBeAbleToRemoveAttributes() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
for (Attribute attribute : tree.getRoot().getAttributes()) {
attribute.remove();
}
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
assertTrue(tree.getRoot().getAttributes().isEmpty());
}
@Test
public void shouldNotDestroyFormattingAfterSimpleElementInsertion() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
final Element name = tree.getSingleElement("/project/name");
name.insertAfter(NewElement.createElement("description", "This is test pom.xml"));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <description>This is test pom.xml</description>\n" +
"</project>");
}
@Test
public void shouldNotDestroyFormattingAfterComplexElementInsertion() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.getSingleElement("//name")
.insertAfter(NewElement.createElement("dependencies", NewElement.createElement("dependency",
NewElement.createElement("artifactId",
"test-artifact"),
NewElement
.createElement("groupId", "test-group"),
NewElement.createElement("version",
"test-version"))));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version>test-version</version>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>");
assertEquals(tree.getSingleText("/project/dependencies/dependency/artifactId"), "test-artifact");
}
@Test
public void shouldNotDestroyFormattingAfterRemovingElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version>test-version</version>\n" +
" <scope>compile</scope>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>");
tree.removeElement("/project/dependencies/dependency[1]/scope");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version>test-version</version>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>");
}
@Test
public void shouldNotDestroyFormattingAfterRemovingElementWithChildren() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version>test-version</version>\n" +
" <scope>compile</scope>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>");
tree.removeElement("/project/dependencies");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
}
@Test
public void batchUpdateShouldProduceExpectedContent() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
//removing parent
tree.removeElement("//parent");
//removing configuration
tree.getSingleElement("//configuration").remove();
//adding groupId before artifactId and version after
tree.getSingleElement("/project/artifactId")
.insertBefore(NewElement.createElement("groupId", "test-group"))
.insertAfter(NewElement.createElement("version", "test-version"));
//delete all test dependencies
for (Element element : tree.getElements("//dependency[scope='test']")) {
element.remove();
}
//adding junit dependency to the end of dependencies list
tree.getSingleElement("//dependencies")
.appendChild(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "junit"),
NewElement.createElement("groupId", "junit"),
NewElement.createElement("version", "4.0")));
//change junit version
tree.updateText("//dependency[artifactId='junit']/version", "4.1");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <groupId>test-group</groupId>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <version>test-version</version>\n" +
" <packaging>jar</packaging>\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <groupId>com.google.guava</groupId>\n" +
" <artifactId>guava</artifactId>\n" +
" <version>18.0</version>\n" +
" </dependency>\n" +
" <!-- Test dependencies -->\n" +
" <dependency>\n" +
" <artifactId>junit</artifactId>\n" +
" <groupId>junit</groupId>\n" +
" <version>4.1</version>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>\n");
}
@Test
public void shouldBeAbleToAppendChildToEmptyElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies></dependencies>\n" +
"</project>");
tree.getSingleElement("//dependencies")
.appendChild(NewElement.createElement("dependency",
NewElement.createElement("artifactId", "test-artifact"),
NewElement.createElement("groupId", "test-group"),
NewElement.createElement("version", "test-version")));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
" <dependencies>\n" +
" <dependency>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version>test-version</version>\n" +
" </dependency></dependencies>\n" +
"</project>");
}
@Test
public void shouldRemoveCommentIfCommentContainerRemoved() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <dependencies>\n" +
" <!-- test dependencies -->\n" +
" <dependency>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <groupId>test-group</groupId>\n" +
" <version>test-version</version>\n" +
" </dependency>\n" +
" </dependencies>\n" +
"</project>");
tree.removeElement("//dependencies");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
"</project>");
}
@Test
public void elementsShouldBeShiftedRightAfterElementTextUpdate() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.updateText("//artifactId", "longer artifact identifier");
//all elements which are right from artifact id
//should be shifted right on "new artifact id length" minus "old artifact id length"
//to check it lets modify elements which are right
tree.removeElement("//packaging");
tree.updateText("//name", "new name");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>longer artifact identifier</artifactId>\n" +
" <!-- project name -->\n" +
" <name>new name</name>\n" +
"</project>");
}
@Test
public void elementsShouldBeShiftedLeftAfterElementTextUpdate() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>long-artifact-identifier</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <!-- project name -->\n" +
" <name>Test</name>\n" +
"</project>");
tree.updateText("//artifactId", "smaller-art-id");
//all elements which are right from artifact id
//should be shifted left on "old artifact id length" minus "new artifact id length"
//to check it lets modify elements which are right
tree.removeElement("//packaging");
tree.updateText("//name", "new name");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <artifactId>smaller-art-id</artifactId>\n" +
" <!-- project name -->\n" +
" <name>new name</name>\n" +
"</project>");
}
@Test
public void shouldBeAbleToChangeElementEmptyText() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <name></name>\n" +
"</project>");
tree.updateText("//name", "name");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <name>name</name>\n" +
"</project>");
}
@Test
public void textBeforeElementShouldBeRemovedWithElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>text-before<test>text-inside</test>text-after</root>");
tree.removeElement("//test");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>text-after</root>");
}
@Test
public void commentBeforeElementShouldNotBeRemovedWithElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root><!--comment--><test>text-inside</test>text-after</root>");
tree.removeElement("//test");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root><!--comment-->text-after</root>");
}
@Test
public void commentsShouldNotBeRemovedAfterElementTextUpdate() {
final XMLTree tree = XMLTree.from("<root>" +
"<!--comment1-->" +
"<!--comment2-->" +
"<!--long \n" +
"comment3-->" +
"text" +
"</root>");
tree.getRoot().setText("new text");
assertEquals(tree.toString(), "<root>" +
"<!--comment1-->" +
"<!--comment2-->" +
"<!--long \n" +
"comment3-->" +
"new text" +
"</root>");
}
@Test
public void textUpdateShouldNotRemoveElements() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>" +
"text-before" +
"<!--comment-->" +
"<test>text-inside</test>" +
"text-after" +
"</root>");
tree.getRoot().setText("new text");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<root>" +
"new text" +
"<!--comment-->" +
"<test>text-inside</test>" +
"</root>");
}
@Test
public void childrenShouldNotBeRemovedAfterParentTextUpdate() {
final XMLTree tree = XMLTree.from("<root><inner></inner><inner></inner></root>");
tree.getRoot().setText("root text");
assertEquals(tree.toString(), "<root>root text<inner></inner><inner></inner></root>");
assertEquals(tree.getRoot().getText(), "root text");
}
@Test
public void shouldBeAbleToRemoveVoidElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project name=\"MyProject\" default=\"dist\" basedir=\".\">\n" +
" <description>\n" +
" simple example build file\n" +
" </description>\n" +
" <!-- set global properties for this build -->\n" +
" <property name=\"src\" location=\"src\"/>\n" +
" <property name=\"build\" location=\"build\"/>\n" +
" <property name=\"dist\" location=\"dist\"/>\n" +
" <target name=\"init\">\n" +
" <!-- Create the time stamp -->\n" +
" <tstamp/>\n" +
" <!-- Create the build directory structure used by compile -->\n" +
" <mkdir dir=\"${build}\"/>\n" +
" </target>\n" +
"</project>");
tree.getSingleElement("//property[@name='build']").remove();
tree.getSingleElement("//property[@name='src']").remove();
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project name=\"MyProject\" default=\"dist\" basedir=\".\">\n" +
" <description>\n" +
" simple example build file\n" +
" </description>\n" +
" <!-- set global properties for this build -->\n" +
" <property name=\"dist\" location=\"dist\"/>\n" +
" <target name=\"init\">\n" +
" <!-- Create the time stamp -->\n" +
" <tstamp/>\n" +
" <!-- Create the build directory structure used by compile -->\n" +
" <mkdir dir=\"${build}\"/>\n" +
" </target>\n" +
"</project>");
}
@Test
public void shouldBeAbleToChangeAttributeValueOfVoidElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project name=\"MyProject\" default=\"dist\" basedir=\".\">\n" +
" <description>\n" +
" simple example build file\n" +
" </description>\n" +
" <!-- set global properties for this build -->\n" +
" <property name=\"src\" location=\"src\"/>\n" +
" <property name=\"build\" location=\"build\"/>\n" +
" <property name=\"dist\" location=\"dist\"/>\n" +
" <target name=\"init\">\n" +
" <!-- Create the time stamp -->\n" +
" <tstamp/>\n" +
" <!-- Create the build directory structure used by compile -->\n" +
" <mkdir dir=\"${build}\"/>\n" +
" </target>\n" +
"</project>");
tree.getSingleElement("//property[@name='build']")
.getAttribute("location")
.setValue("other-build");
//to check that segments were shifted
tree.removeElement("//tstamp");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project name=\"MyProject\" default=\"dist\" basedir=\".\">\n" +
" <description>\n" +
" simple example build file\n" +
" </description>\n" +
" <!-- set global properties for this build -->\n" +
" <property name=\"src\" location=\"src\"/>\n" +
" <property name=\"build\" location=\"other-build\"/>\n" +
" <property name=\"dist\" location=\"dist\"/>\n" +
" <target name=\"init\">\n" +
" <!-- Create the time stamp -->\n" +
" <!-- Create the build directory structure used by compile -->\n" +
" <mkdir dir=\"${build}\"/>\n" +
" </target>\n" +
"</project>");
}
@Test
public void shouldBeAbleToGetCDATATextContent() {
final String CDATA = "Maven's model for the old archetype descriptor (ie for Archetype 1.0.x).";
final XMLTree tree = XMLTree.from("<model>\n" +
" <id>archetype</id>\n" +
" <name>Archetype</name>\n" +
" <description><![CDATA[" + CDATA + "]]></description>\n" +
"</model>");
//AS tree#getSingleText uses XPath for selecting text content
//we can easily select CDATA from element
assertEquals(tree.getSingleText("/model/description"), CDATA);
assertTrue(tree.getSingleElement("/model/description").getText().isEmpty());
}
@Test
public void shouldBeAbleToCreateTreeFromRootName() {
final XMLTree tree = XMLTree.create("project");
tree.getRoot()
.setAttribute("xmlns", "http://maven.apache.org/POM/4.0.0")
.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
.setAttribute("xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd")
.appendChild(NewElement.createElement("modelVersion", "4.0.0"))
.appendChild(NewElement.createElement("parent",
NewElement.createElement("artifactId", "test-parent"),
NewElement.createElement("groupId", "test-parent-group-id"),
NewElement.createElement("version", "test-parent-version")))
.appendChild(NewElement.createElement("artifactId", "test-artifact"))
.appendChild(NewElement.createElement("packaging", "jar"))
.appendChild(NewElement.createElement("name", "test"));
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 " +
"http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <parent>\n" +
" <artifactId>test-parent</artifactId>\n" +
" <groupId>test-parent-group-id</groupId>\n" +
" <version>test-parent-version</version>\n" +
" </parent>\n" +
" <artifactId>test-artifact</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <name>test</name>\n" +
"</project>");
}
@Test
public void shouldBeAbleToAddElementWithPrefix() {
final XMLTree tree = XMLTree.from("<examples:tests xmlns:examples=\"http://whatever.com/\">\n" +
" <examples:test>first</examples:test>\n" +
"</examples:tests>");
tree.getRoot()
.appendChild(NewElement.createElement("examples:test", "second"));
assertEquals(tree.toString(), "<examples:tests xmlns:examples=\"http://whatever.com/\">\n" +
" <examples:test>first</examples:test>\n" +
" <examples:test>second</examples:test>\n" +
"</examples:tests>");
final Element appended = tree.getRoot().getLastChild();
assertEquals(appended.getLocalName(), "test");
assertEquals(appended.getPrefix(), "examples");
assertEquals(appended.getName(), "examples:test");
}
@Test
public void shouldBeAbleToCreateTreeFromXMLWhichContainsInstructionElement() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <configuration>\n" +
" <tasks>\n" +
" <?SORTPOM IGNORE?>\n" +
" <echo append=\"false\" file=\"${project.build.directory}/classes/com/codenvy/ide/BuildInfo.properties\">\n" +
" revision= ${revision}\n" +
" buildTime = ${timestamp}\n" +
" version = ${codenvy.cloud-ide.version}\n" +
" </echo>\n" +
" <?SORTPOM RESUME?>\n" +
" </tasks>\n" +
" </configuration>\n" +
"</project>");
tree.updateText("//echo", "new text content");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
" <configuration>\n" +
" <tasks>\n" +
" <?SORTPOM IGNORE?>\n" +
" <echo append=\"false\" file=\"${project.build.directory}/classes/com/codenvy/ide/BuildInfo.properties\">new text content</echo>\n" +
" <?SORTPOM RESUME?>\n" +
" </tasks>\n" +
" </configuration>\n" +
"</project>");
}
@Test
public void shouldBeAbleToCreateTreeFromXMLWhichContainsCoupleOfCDATAElements() {
final XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
"<!-- Spring security authen/authorize query string -->\n" +
"<security.query.authen>\n" +
"<![CDATA[\n" +
"select u.login as user, u.password as password, case when u.status = 'ok' " +
"then 1 else 0 end as enabled \n" +
"from ${jdbc.default.schema}.USER u \n" +
"where u.login = ? and u.status = 'ok'" +
"]]>\n\n\n\n" +
"</security.query.authen>\n" +
"<security.query.authorize>\n" +
"<![CDATA[\n" +
"select u.login as user, u.password as password, case when u.status = 'ok' " +
"then 1 else 0 end as enabled \n" +
"from ${jdbc.default.schema}.USER u \n" +
"where u.login = ? and u.status = 'ok'" +
"]]>\na" +
"</security.query.authorize>\n" +
"</project>");
tree.removeElement("//security.query.authorize");
tree.updateText("//security.query.authen", "new-text");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project>\n" +
"<!-- Spring security authen/authorize query string -->\n" +
"<security.query.authen>new-text</security.query.authen>\n" +
"</project>");
}
@Test(expectedExceptions = XMLTreeException.class,
expectedExceptionsMessageRegExp = "Operation not permitted for element which has been removed from XMLTree")
public void shouldNotBeAbleToUseElementWhenParentWasRemovedFromTree() {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Element firstDep = tree.getSingleElement("/project/dependencies/dependency[1]");
assertNotNull(firstDep.getText());
tree.removeElement("/project/dependencies");
firstDep.getText();
}
@Test
public void shouldBeAbleToWriteTreeBytesToPath() throws Exception {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Path path = targetDir().resolve("test-xml.xml");
tree.writeTo(path);
assertTrue(exists(path));
assertEquals(readAllBytes(path), tree.getBytes());
delete(path);
}
@Test
public void shouldBeABleToWriteTreeBytesToFile() throws Exception {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final java.io.File file = targetDir().resolve("test-xml.xml").toFile();
tree.writeTo(file);
assertTrue(file.exists());
assertEquals(toByteArray(file), tree.getBytes());
assertTrue(file.delete());
}
@Test
public void shouldBeAbleToWriteTreeBytesToOutputStream() throws Exception {
final XMLTree tree = XMLTree.from(XML_CONTENT);
final Path path = targetDir().resolve("test-xml.xml");
try (OutputStream os = newOutputStream(path)) {
tree.writeTo(os);
}
assertTrue(exists(path));
assertEquals(readAllBytes(path), tree.getBytes());
delete(path);
}
@Test
public void shouldBeAbleToCreateTreeFromPath() throws Exception {
final byte[] bytes = XML_CONTENT.getBytes();
final Path path = targetDir().resolve("test-xml.xml");
write(path, bytes);
final XMLTree tree = XMLTree.from(path);
assertEquals(tree.getBytes(), bytes);
delete(path);
}
@Test
public void shouldBeAbleToCreateTreeFromFile() throws Exception {
final byte[] bytes = XML_CONTENT.getBytes();
final Path path = targetDir().resolve("test-xml.xml");
write(path, bytes);
final XMLTree tree = XMLTree.from(path.toFile());
assertEquals(tree.getBytes(), bytes);
delete(path);
}
@Test
public void shouldBeAbleToCreateTreeFromInputStream() throws Exception {
final byte[] bytes = XML_CONTENT.getBytes();
final XMLTree tree = XMLTree.from(new ByteArrayInputStream(bytes));
assertEquals(tree.getBytes(), bytes);
}
@Test
public void shouldBeAbleToCreateTreeFromXMLWhichContainsCDATAAndTextUnderSameParent() {
final XMLTree tree = XMLTree.from("<parent>\n" +
"TEXT" +
"<![CDATA[ CDATA CONTENT ]]>\n" +
"TEXT AGAIN" +
"<child></child>" +
"</parent>");
assertEquals(tree.getRoot().getText(), "\n" +
"TEXT\n" +
"TEXT AGAIN");
tree.updateText("/parent", "new text");
assertEquals(tree.toString(), "<parent>new text<child></child></parent>");
}
@Test
public void shouldIncludeCarriageReturnCharacterOffsetWhileParsingXMLContent() {
System.setProperty("line.separator", "\n");
final XMLTree tree = XMLTree.from("<parent>\n" +
" <child1>\r\r\r\r\rchild1 text\r</child1>\n" +
"\r\r<child2>child 2 text</child2>\n" +
"</parent>");
tree.updateText("/parent/child1", "new text");
tree.updateText("/parent/child2", "new text");
assertEquals(tree.toString(), "<parent>\n" +
" <child1>new text</child1>\n" +
"\n\n<child2>new text</child2>\n" +
"</parent>");
}
@Test
public void shouldIncludeCarriageReturnCharacterOffsetWhileParsingXMLContent2() {
System.setProperty("line.separator", "\n");
final XMLTree tree = XMLTree.from("<parent>\n" +
" <child1>\rchild1 text\r</child1>\n" +
"\r\r<child2>child 2 text</child2>\n" +
"</parent>");
tree.insertAfter("/parent/child1", NewElement.createElement("newTag"));
assertEquals(tree.toString(), "<parent>\n" +
" <child1>\nchild1 text\n</child1>\n" +
" <newTag/>\n" +
"\n\n<child2>child 2 text</child2>\n" +
"</parent>");
}
@Test
public void shouldRespectContentPositionsWhenUpdatingTextWithCarriageReturnCharacter() {
System.setProperty("line.separator", "\r\n");
final String XML = "<parent><child>\r\nchild text\r\n</child></parent>";
XMLTree tree = XMLTree.from(XML);
tree.updateText("/parent/child", "new text");
assertEquals(tree.toString(), "<parent><child>new text</child></parent>");
}
@Test
public void shouldParseWithCarriageReturnCharacterInDocumentPrologue() {
System.setProperty("line.separator", "\r");
XMLTree tree = XMLTree.from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!-- <<<<< COMMENT >>>>> -->\n" +
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r" +
"<project>\r\r\r\r\n" +
" <name>\r\n\r\nname\r\n\r\n</name>" +
" <packaging>\r\r\r\n\n\nwar</packaging>" +
"</project>");
tree.updateText("/project/packaging", "jar");
assertEquals(tree.getSingleText("/project/name"), "\n\n\n\nname\n\n\n\n");
assertEquals(tree.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r" +
"<!-- <<<<< COMMENT >>>>> -->\r" +
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r" +
"<project>\r\r\r\r\r" +
" <name>\r\r\r\rname\r\r\r\r</name>" +
" <packaging>jar</packaging>" +
"</project>");
}
@Test
public void shouldParseContentWithCarriageReturnCharacterBetweenTagAttributes() {
System.setProperty("line.separator", "\r\n");
final String XML = "<parent \r\n\r\n\r\n attr1=\"v\"><child>\r\nchild text\r\n</child></parent>";
XMLTree tree = XMLTree.from(XML);
tree.updateText("/parent/child", "new text");
assertEquals(tree.toString(), "<parent \r\n\r\n\r\n attr1=\"v\"><child>new text</child></parent>");
}
@Test(dataProvider = "custom-xml-files")
public void shouldBeAbleToCreateTreeFromCustomXML(File xml) throws IOException {
//should be able to parse file
try {
XMLTree.from(xml);
} catch (XMLTreeException ex) {
throw new XMLTreeException(ex.getMessage() + " file: " + xml.getAbsolutePath());
}
}
@DataProvider(name = "custom-xml-files")
public Object[][] getCustomXMLFiles() throws Exception {
final URL url = Thread.currentThread().getContextClassLoader().getResource(".");
assertNotNull(url);
final File testFilesRoot = Paths.get(url.toURI()).resolve("test-xml-files").toFile();
final File[] files = testFilesRoot.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return !file.isDirectory() && file.getName().endsWith(".xml");
}
});
final Object[][] data = new Object[files.length][];
for (int i = 0; i < files.length; i++) {
data[i] = new Object[]{files[i]};
}
return data;
}
private Path targetDir() throws URISyntaxException {
final URL url = Thread.currentThread().getContextClassLoader().getResource(".");
assertNotNull(url);
return Paths.get(url.toURI()).getParent();
}
}