blob: 436e1ea96c73494684d36e9a3229b008db208fb2 [file] [log] [blame]
/************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
*
* Use is subject to license terms.
*
* 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. You can also
* obtain a copy of the License at http://odftoolkit.org/docs/license.txt
*
* 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 org.odftoolkit.odfdom.dom;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import org.junit.Assert;
import org.junit.Test;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.pkg.OdfAlienElement;
import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.doc.OdfPresentationDocument;
import org.odftoolkit.odfdom.utils.ResourceUtilities;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XPathTest {
private static final Logger LOG = Logger.getLogger(XPathTest.class.getName());
private static final String SOURCE_FILE_1 = "XPathTest-foreignPrefix.odp";
private static final String SOURCE_FILE_2 = "XPathTest-foreignPrefix2.odp";
private static final String SOURCE_FILE_3 = "XPathTest-duplicate-prefix.odt";
/**
* 1) The first test document "XPathTest-foreignPrefix.odp" uses the prefix "daisy" instead of "office" for ODF XML elements.
<daisy:document-content xmlns:daisy="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="ur...
<daisy:scripts/>
<daisy:automatic-styles>
* 2) The test doc also uses multiple identical namespace prefixes with different URIs.
* <text:p>Slide
* <draw:element1 xmlns:draw="urn://dummy-namespace-one">
* <draw:element2 xmlns:draw="urn://dummy-namespace-two"
* draw:attribute2="importantValue">dummy</draw:element2></draw:element1>One!!</text:p>
* It will be tested, if they have been renamed correctly.
* 3) The test doc also uses multiple different namespace prefixes with the similar URIs.
* Testing getPrefixes(String URI) from the NamespaceContext interface.
* <text:p>Slide
* <prefixOne:element1 xmlns:prefixOne="urn://some-test-odfdom-namespace">
* <prefixTwo:element2 xmlns:prefixTwo="urn://some-test-odfdom-namespace"
* prefixTwo:attribute2="importantValue">dummy</prefixTwo:element2></prefixOne:element1>Two!!</text:p>
*
* 4) Having element and attribute without namespace
* <!-- element and attribute without namespace with an attribute value with a namespace prefix as well -->
<text:p xmlns:alien="urn://some-test-attribute-value-namespace"
* foreign="alien:valueOfAlienAttribute">Some<test>good</test> Content!!</text:p>
*/
@Test
public void testXPathwithAlienNodes() throws Exception {
try {
OdfPresentationDocument odpWithSlides = OdfPresentationDocument.loadDocument(ResourceUtilities.getAbsolutePath(SOURCE_FILE_1));
OdfFileDom contentDom = odpWithSlides.getContentDom();
XPath xpath = contentDom.getXPath();
// Test scenario 1 - see comment above
Iterator<String> prefixes = contentDom.getPrefixes("urn:oasis:names:tc:opendocument:xmlns:office:1.0");
// The first prefix have to be "office"
String prefix = prefixes.next();
Assert.assertTrue(prefix.equals("office") || prefix.equals("daisy"));
if(prefix.equals("office")){
prefix = prefixes.next();
Assert.assertTrue(prefix.equals("daisy"));
}else if(prefix.equals("daisy")){
prefix = prefixes.next();
Assert.assertTrue(prefix.equals("office"));
}else{
Assert.fail();
}
// There should be no further prefix
Assert.assertFalse(prefixes.hasNext());
Iterator<String> prefixes2 = contentDom.getPrefixes("urn://some-test-odfdom-namespace");
prefix = prefixes2.next();
Assert.assertTrue(prefix.equals("prefixOne") || prefix.equals("prefixTwo"));
if(prefix.equals("prefixOne")){
prefix = prefixes2.next();
Assert.assertTrue(prefix.equals("prefixTwo"));
}else if(prefix.equals("prefixTwo")){
prefix = prefixes2.next();
Assert.assertTrue(prefix.equals("prefixOne"));
}else{
Assert.fail();
}
// There should be no further prefix
Assert.assertFalse(prefixes.hasNext());
Node rootNode = contentDom.getRootElement();
odpWithSlides.save(ResourceUtilities.newTestOutputFile("XPathTest-ForeignPrefix-output.odp"));
if (rootNode instanceof OdfAlienElement) {
Assert.fail("The none OOO default prefix for office: was not exchanged!");
}
NodeList styleNameAttributes = (NodeList) xpath.evaluate(".//*[@style:name]", rootNode, XPathConstants.NODESET);
LOG.log(Level.INFO, "Amount of style:name is {0}", styleNameAttributes.getLength());
Assert.assertTrue(styleNameAttributes.getLength() == 11);
// test if the identical namespace prefixes with different URI have been renamed correctly (earlier draw:element1/draw:element2).
String attributeWithDuplicatePrefix = (String) xpath.evaluate(".//draw__1:element1/draw__2:element2/@draw__2:attribute2", rootNode, XPathConstants.STRING);
Assert.assertTrue(attributeWithDuplicatePrefix.equals("importantValue"));
Assert.assertEquals("urn:oasis:names:tc:opendocument:xmlns:office:1.0", xpath.getNamespaceContext().getNamespaceURI("office"));
Assert.assertEquals("http://www.w3.org/1999/xlink", xpath.getNamespaceContext().getNamespaceURI("xlink"));
String alienAttributeValue = (String) xpath.evaluate(".//*/@foreign", rootNode, XPathConstants.STRING);
LOG.log(Level.INFO, "The value of the alien attribute is {0}, expected is ''alien:valueOfAlienAttribute''!", alienAttributeValue);
Assert.assertEquals("alien:valueOfAlienAttribute", alienAttributeValue);
String alienElementValue = (String) xpath.evaluate("//text:p/test", rootNode, XPathConstants.STRING);
LOG.log(Level.INFO, "The value of the alien element is {0}, expected is ''good''!", alienElementValue);
Assert.assertEquals("good", alienElementValue);
LOG.log(Level.INFO, "Amount of @alien:foreignAttribute and @style:name is {0}", ((NodeList) xpath.evaluate(".//*[@alien:foreignAttribute or @style:name]", rootNode, XPathConstants.NODESET)).getLength());
Assert.assertTrue("Amount of @alien:foreignAttribute and @style:name is not 13!!", ((NodeList) xpath.evaluate(".//*[@alien:foreignAttribute or @style:name]", rootNode, XPathConstants.NODESET)).getLength() == 13);
// Test if an empty iterator is being returned for a none existing URL
Iterator<String> prefixes3 = contentDom.getPrefixes("urn://this-prefix-does-not-exist-in-the-xml");
Assert.assertFalse("Not used prefix returned a none-empty iterator!", prefixes3.hasNext());
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
Assert.fail(e.toString());
}
}
/**
* A typical test, that deals with xlinks in SOURCE_FILE_2
*/
@Test
public void testCopyForeignSlide() {
try {
OdfPresentationDocument targetodp = OdfPresentationDocument.loadDocument(ResourceUtilities.getAbsolutePath(SOURCE_FILE_1));
OdfPresentationDocument sourceodp = OdfPresentationDocument.loadDocument(ResourceUtilities.getAbsolutePath(SOURCE_FILE_2));
int slidecount = sourceodp.getSlideCount();
for (int i = 0; i < slidecount; i++) {
targetodp.copyForeignSlide(i, sourceodp, i);
}
targetodp.save(ResourceUtilities.newTestOutputFile("XPathTest-ForeignPrefix2-output.odp"));
targetodp.close();
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
Assert.fail(e.toString());
}
}
/**
* This test SHOULD fail, but it isn't. Its source code is identical to the first test in this unit test
* @throws Exception
*/
@Test
public void testXPathIsMissingXLinkButItWillPassBecauseItTheSecondTestInThisUnitTest() throws Exception {
try {
OdfPresentationDocument odpWithSlides = OdfPresentationDocument.loadDocument(ResourceUtilities.getAbsolutePath(SOURCE_FILE_1));
OdfFileDom contentDom = odpWithSlides.getContentDom();
XPath xpath = contentDom.getXPath();
Node node = odpWithSlides.getContentDom().getRootElement();
NodeList linkNodes = (NodeList) xpath.evaluate(".//*[@xlink:href]", node, XPathConstants.NODESET);
Assert.assertNotNull(linkNodes);
Assert.assertEquals("urn:oasis:names:tc:opendocument:xmlns:office:1.0", xpath.getNamespaceContext().getNamespaceURI("office"));
Assert.assertEquals("http://www.w3.org/1999/xlink", xpath.getNamespaceContext().getNamespaceURI("xlink"));
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
Assert.fail(e.toString());
}
}
/**
* This test checks if the XPath returned by OdfFileDom is correctly aware of namespacess.
* The NamespaceContext implementation in OdfFileDom is aware of duplicate prefixes, but getNamespaceURI(prefix)
* in OdfFileDom does not implement it correctly
*
* With the patch applied in OdfFileDom these tests pass correctly
*
* sample metadata rdf generate from Openoffice 3.3 looks like this :
* <?xml version="1.0" encoding="utf-8"?>
* <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
* <rdf:Description rdf:about="../content.xml#id1366098766">
* <ns1:BungeniActionEvent xmlns:ns1="http://editor.bungeni.org/1.0/anx/"></ns1:BungeniActionEvent>
* <ns2:BungeniSectionID xmlns:ns2="http://editor.bungeni.org/1.0/anx/">Xda+5VC/SQKKG7Bk83a2JA</ns2:BungeniSectionID>
* <ns3:BungeniSectionType xmlns:ns3="http://editor.bungeni.org/1.0/anx/">Conclusion</ns3:BungeniSectionType>
* <ns4:hiddenBungeniMetaEditable xmlns:ns4="http://editor.bungeni.org/1.0/anx/">false</ns4:hiddenBungeniMetaEditable>
* </rdf:Description>
*
* @throws Exception
*/
@Test
public void testXPathDuplicatePrefixForForeignNamespace() throws Exception{
try {
OdfDocument odfDoc = OdfDocument.loadDocument(ResourceUtilities.getAbsolutePath(SOURCE_FILE_3));
OdfFileDom fileDom = odfDoc.getFileDom("meta/meta.rdf");
// add additional duplicate NS prefixes to the DOM
fileDom.setNamespace("anx", "http://editor.bungeni.org/1.0/anx/");
fileDom.setNamespace("myrdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
//get the XPath from the file dom and set its NS context to the OdfFileDom object
XPath xpathFileDom = fileDom.getXPath();
xpathFileDom.setNamespaceContext(fileDom);
//PASS - this works correctly
String rdfNsUri = fileDom.getNamespaceURI("rdf");
LOG.log(Level.INFO, "The value of the nsuri is {0} expected ns-uri is ''http://www.w3.org/1999/02/22-rdf-syntax-ns#''", rdfNsUri);
Assert.assertEquals("http://www.w3.org/1999/02/22-rdf-syntax-ns#", rdfNsUri);
//FAIL - for duplicate RDF ns prefix
String myrdfNsUri = fileDom.getNamespaceURI("myrdf");
LOG.log(Level.INFO, "The value of the nsuri is {0} expected ns-uri is ''http://www.w3.org/1999/02/22-rdf-syntax-ns#''", myrdfNsUri);
Assert.assertEquals("http://www.w3.org/1999/02/22-rdf-syntax-ns#", myrdfNsUri);
//PASS - for custom NS prefix in document, only the first one
String anxNsUri1 = fileDom.getNamespaceURI("ns1");
LOG.log(Level.INFO, "The value of the nsuri is {0} expected ns-uri is ''http://editor.bungeni.org/1.0/anx/''", anxNsUri1);
Assert.assertEquals("http://editor.bungeni.org/1.0/anx/", anxNsUri1);
//FAIL - for custom NS prefix in document ns3, ns4, ns...
String anxNsUri2 = fileDom.getNamespaceURI("ns2");
LOG.log(Level.INFO, "The value of the ns-uri is {0} expected ns-uri is ''http://editor.bungeni.org/1.0/anx/''", anxNsUri2);
Assert.assertEquals("http://editor.bungeni.org/1.0/anx/", anxNsUri2);
//FAIL - for custom duplicate NS prefix anx
String anxNsUriCustom = fileDom.getNamespaceURI("anx");
LOG.log(Level.INFO, "The value of the ns-uri is {0} expected ns-uri is ''http://editor.bungeni.org/1.0/anx/''", anxNsUriCustom);
Assert.assertEquals("http://editor.bungeni.org/1.0/anx/", anxNsUriCustom);
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
Assert.fail(e.toString());
}
}
}