From: <ker...@us...> - 2010-03-13 13:20:27
|
Revision: 17459 http://jedit.svn.sourceforge.net/jedit/?rev=17459&view=rev Author: kerik-sf Date: 2010-03-13 13:20:20 +0000 (Sat, 13 Mar 2010) Log Message: ----------- - XPath tool is XPath 2.0 compatible (requires SaxonPlugin) - more tests Modified Paths: -------------- plugins/XSLT/trunk/XSLT.props plugins/XSLT/trunk/build.xml plugins/XSLT/trunk/docs/users-guide.xml plugins/XSLT/trunk/test/build.xml plugins/XSLT/trunk/test/xslt/XSLTOptionPaneTest.java plugins/XSLT/trunk/test/xslt/XSLTPluginTest.java plugins/XSLT/trunk/test/xslt/XSLTPluginXPathTest.java plugins/XSLT/trunk/test/xslt/XSLTSettingsTest.java plugins/XSLT/trunk/xslt/PropertyUtil.java plugins/XSLT/trunk/xslt/XMLFragmentsString.java plugins/XSLT/trunk/xslt/XPathTool.java plugins/XSLT/trunk/xslt/XSLTOptionPane.java plugins/XSLT/trunk/xslt/XsltActions.java Added Paths: ----------- plugins/XSLT/trunk/test/xslt/Saxon9XPathAdapterTest.java plugins/XSLT/trunk/test/xslt/XalanXPathAdapterTest.java plugins/XSLT/trunk/xslt/Saxon9XPathAdapter.java plugins/XSLT/trunk/xslt/XPathAdapter.java plugins/XSLT/trunk/xslt/XalanXPathAdapter.java plugins/XSLT/trunk/xslt/XalanXPathNode.java Removed Paths: ------------- plugins/XSLT/trunk/xslt/XPathNode.java Modified: plugins/XSLT/trunk/XSLT.props =================================================================== --- plugins/XSLT/trunk/XSLT.props 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/XSLT.props 2010-03-13 13:20:20 UTC (rev 17459) @@ -8,6 +8,7 @@ plugin.xslt.XSLTPlugin.depend.1=jedit 04.03.99.01 plugin.xslt.XSLTPlugin.depend.2=plugin xml.XmlPlugin 2.5 plugin.xslt.XSLTPlugin.depend.3=plugin errorlist.ErrorListPlugin 1.8 +plugin.xslt.XSLTPlugin.depend.4=optional plugin saxon.SaxonPLugin 9.2.0.6 # XSLT system properties javax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl @@ -15,13 +16,24 @@ org.xml.sax.driver=org.apache.xerces.parsers.SAXParser # XSLT engines : -xslt.factory.org.apache.xalan.processor.TransformerFactoryImpl=XSLT 1.0 - Xalan 2.7.1 (org.apache.xalan.processor.TransformerFactoryImpl) -xslt.factory.com.icl.saxon.TransformerFactoryImpl=XSLT 1.0 - Saxon 6.5.5 (com.icl.saxon.TransformerFactoryImpl) -xslt.factory.net.sf.saxon.TransformerFactoryImpl=XSLT 2.0 - Saxon 9.2 (net.sf.saxon.TransformerFactoryImpl) +xslt.factory.class.0=org.apache.xalan.processor.TransformerFactoryImpl +xslt.factory.label.0=XSLT 1.0 - Xalan 2.7.1 (org.apache.xalan.processor.TransformerFactoryImpl) +xslt.factory.class.1=com.icl.saxon.TransformerFactoryImpl +xslt.factory.label.1=XSLT 1.0 - Saxon 6.5.5 (com.icl.saxon.TransformerFactoryImpl) +xslt.factory.class.2=net.sf.saxon.TransformerFactoryImpl +xslt.factory.label.2=XSLT 2.0 - Saxon 9.2 (net.sf.saxon.TransformerFactoryImpl) # defaults to Xalan xslt.factory=org.apache.xalan.processor.TransformerFactoryImpl +# XPath adapters : +xpath.adapter.class.0=xslt.XalanXPathAdapter +xpath.adapter.label.0=Xalan (XPath 1.0) +xpath.adapter.class.1=xslt.Saxon9XPathAdapter +xpath.adapter.label.1=Saxon 9.2 (XPath 2.0) - requires SaxonPlugin + +xpath.adapter=xslt.XalanXPathAdapter + # Option panes plugin.xslt.XSLTPlugin.option-pane=xslt.general @@ -38,6 +50,19 @@ and restart jEdit (see also the XSLT Plugin manual). options.xslt.factory.error-class-cast=This class doesn't implement javax.xml.transform.sax.SAXTransformerFactory.\n\ You may have to double check the documentation of your XSLT processor. + +options.xpath.adapter.label=XPath engine : +options.xpath.adapter.tooltip=XPath engine for the XPath Tool. If you choose Saxon, ensure that SaxonPlugin is installed. + +options.xpath.adapter.error-not-found=This class can''t be found by jEdit.\n\ + You may obtain the Saxon XSLT processor for XSLT 2.0 via the SaxonPlugin,\n\ +available in the plugin manager.\n\ + Other processors have to be installed manually. Drop the jar file in :\n\ + {0}\n\ + and restart jEdit (see also the XSLT Plugin manual). +options.xpath.adapter.error-class-cast=This class doesn't implement xslt.XPathAdapter.\n\ + XPathAdapter is an interface in the XSLT plugin (see also the XSLT Plugin manual). + options.xslt.compile-on-save.label=compile stylesheets on save options.xslt.compile-on-save.tooltip=this will hopefuly help you catch errors earlier, depending on the XSLT processor # }}} Modified: plugins/XSLT/trunk/build.xml =================================================================== --- plugins/XSLT/trunk/build.xml 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/build.xml 2010-03-13 13:20:20 UTC (rev 17459) @@ -35,7 +35,9 @@ <pathelement location="${jedit.plugins.dir}/ErrorList.jar"/> <pathelement location="${jedit.plugins.dir}/XML.jar"/> <pathelement location="${jedit.install.dir}/jedit.jar"/> - <pathelement location="${jedit.plugins.dir}/serializer.jar"/> + <pathelement location="${serializer.jar}"/> + <pathelement location="${xalan.jar}"/> + <pathelement location="${jedit.plugins.dir}/saxon9he.jar"/> </path> <selector id="extraFiles"> Modified: plugins/XSLT/trunk/docs/users-guide.xml =================================================================== --- plugins/XSLT/trunk/docs/users-guide.xml 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/docs/users-guide.xml 2010-03-13 13:20:20 UTC (rev 17459) @@ -270,6 +270,8 @@ the current buffer. <ulink url="http://www.w3.org/TR/xpath">XPath</ulink> is a W3C-specified expression language used to access or refer to parts of an XML document. + Depending on the XPath engine you choose, you can also use + <ulink url="http://www.w3.org/TR/xpath20/">XPath 2.0</ulink>. </para> <para> To use the XPath Tool: @@ -338,6 +340,17 @@ </listitem> </itemizedlist> </para> + <section id="extending-xpath"><title>Extending the XPath tool</title> + <para>The XPath engine is not as configurable as the XSLT processor, since + the java XPath API (<code>javax.xml.xpath.*</code>) doesn't provide enough + services for the XPath tool. So I had to tap into the native APIs of each engine. + </para> + + <para>If you want to use another XPath engine, you have to implement <code>xslt.XPathAdapter</code>, + package it as a jar, drop it in <filename>"JEDIT_SETTINGS"/jars</filename> + and set the <code>xpath.adapter</code> property to the name of your class. + </para> + </section> </chapter> <chapter id="options"><title>XSLT Plugin option pane</title> @@ -378,6 +391,17 @@ you will be using the selected XSLT processor. </para> + <para>You can also choose an XPath engine to use by selecting one option + in the <guilabel>XPath engine</guilabel> combo-box in the <guimenuitem>Plugins</guimenuitem> / <guimenuitem>XSLT</guimenuitem> + section of the <guimenu>Plugins</guimenu> > <guimenuitem>Plugin Options</guimenuitem> + dialog.</para> + + <itemizedlist> + <listitem><para>for XPath 1.0, use the Xalan engine;</para></listitem> + <listitem><para>for XPath 2.0, use the Saxon 9 engine;</para></listitem> + <listitem><para>to use another engine, see <xref linkend="extending-xpath"/>;</para></listitem> + </itemizedlist> + <para>You can also choose to run a compilation of the stylesheets on save (see <xref linkend="compile-stylesheet"/>). I find it helpful to perform some checks on the stylesheet. @@ -452,6 +476,8 @@ of input,stylesheet and output, as well as a 3 buffers layout.</para></listitem> <listitem><para>XPath tool is namespace aware ; button to grab namespace declarations from source document.</para></listitem> + <listitem><para>XPath tool is XPath 2.0 capable : install SaxonPlugin and + choose it in the Option pane.</para></listitem> </itemizedlist> </para> <para> Modified: plugins/XSLT/trunk/test/build.xml =================================================================== --- plugins/XSLT/trunk/test/build.xml 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/test/build.xml 2010-03-13 13:20:20 UTC (rev 17459) @@ -87,7 +87,7 @@ <!-- this selector holds just one test. This is optional. --> <selector id="testcases.current"> - <filename name="xslt/BufferOrFileVFSSelectorTest.java"/> + <filename name="xslt/XSLTPluginXPathTest.java"/> </selector> <!-- this selector controls which tests to run, set the refid to either Added: plugins/XSLT/trunk/test/xslt/Saxon9XPathAdapterTest.java =================================================================== --- plugins/XSLT/trunk/test/xslt/Saxon9XPathAdapterTest.java (rev 0) +++ plugins/XSLT/trunk/test/xslt/Saxon9XPathAdapterTest.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -0,0 +1,222 @@ +/* + * Saxon9XPathAdapterTest.java + * :folding=explicit:collapseFolds=1: + * + * Copyright (C) 2010 Eric Le Lay + * + * The XSLT plugin is licensed under the GNU General Public License, with + * the following exception: + * + * "Permission is granted to link this code with software released under + * the Apache license version 2.0, for example used by the Xalan package." + */ +package xslt; + +// {{{ jUnit imports +import java.util.concurrent.TimeUnit; + +import org.junit.*; +import static org.junit.Assert.*; + +import org.fest.swing.fixture.*; +import org.fest.swing.core.*; +import org.fest.swing.data.TableCell; +import org.fest.swing.finder.*; +import org.fest.swing.edt.*; +import org.fest.swing.timing.*; +import org.fest.swing.core.matcher.JButtonMatcher; +import org.fest.swing.core.matcher.JTextComponentMatcher; + +import static org.fest.assertions.Assertions.*; + +import org.gjt.sp.jedit.testframework.Log; + +import static org.gjt.sp.jedit.testframework.TestUtils.*; +import static org.gjt.sp.jedit.testframework.EBFixture.*; +import org.gjt.sp.jedit.testframework.PluginOptionsFixture; +import org.gjt.sp.jedit.testframework.TestUtils; + +// }}} + +import org.gjt.sp.jedit.jEdit; +import org.gjt.sp.jedit.Buffer; + +import java.io.*; +import java.util.regex.Pattern; +import java.util.*; + +import org.w3c.dom.Document; + +/** + * unit tests of the Saxon 9 XPath engine adapter + * $Id$ + */ +public class Saxon9XPathAdapterTest{ + private static File testData; + + @BeforeClass + public static void setUpjEdit() throws IOException{ + TestUtils.beforeClass(); + testData = new File(System.getProperty("test_data")).getCanonicalFile(); + assertTrue(testData.exists()); + } + + @AfterClass + public static void tearDownjEdit() { + TestUtils.afterClass(); + } + + @Test + public void testElement() throws Exception{ + final File xsl = new File(testData,"simple/transform.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + Saxon9XPathAdapter xpath = new Saxon9XPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "/xsl:stylesheet"); + + assertEquals("element()",res.getType()); + assertThat(res.getStringValue()).contains("hello"); + + assertTrue(res.isNodeSet()); + assertEquals(1,res.size()); + + XPathAdapter.XPathNode n = res.get(0); + assertTrue(n.hasExpandedName()); + assertFalse(n.hasDomValue()); + assertEquals("element()",n.getType()); + assertEquals("xsl:stylesheet",n.getName()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(1,frags.getFragmentCount()); + } + + @Test + public void testComment() throws Exception{ + final File xsl = new File(testData,"base_uri_bug/base-uri-bug.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + Saxon9XPathAdapter xpath = new Saxon9XPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "//comment()"); + + assertEquals("comment()",res.getType()); + assertThat(res.getStringValue()).contains("this stylesheet was submitted"); + + assertTrue(res.isNodeSet()); + assertEquals(1,res.size()); + + XPathAdapter.XPathNode n = res.get(0); + assertFalse(n.hasExpandedName()); + assertTrue(n.hasDomValue()); + assertEquals("comment()",n.getType()); + assertEquals("",n.getName()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(1,frags.getFragmentCount()); + } + + @Test + public void testNumberSequence() throws Exception{ + final File xsl = new File(testData,"simple/transform.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + Saxon9XPathAdapter xpath = new Saxon9XPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "(1+1,1 div 2)"); + + assertEquals("sequence of xs:decimal",res.getType()); + assertEquals("2 0.5",res.getStringValue()); + + assertTrue(res.isNodeSet()); + assertEquals(2,res.size()); + + XPathAdapter.XPathNode n = res.get(0); + assertFalse(n.hasExpandedName()); + assertTrue(n.hasDomValue()); + assertEquals("xs:integer",n.getType()); + assertEquals("2",n.getDomValue()); + assertEquals(null,n.getName()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(2,frags.getFragmentCount()); + } + + @Test + public void testEmptySequence() throws Exception{ + final File xsl = new File(testData,"simple/transform.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + Saxon9XPathAdapter xpath = new Saxon9XPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "/xsl:transform"); + + assertEquals("empty sequence",res.getType()); + assertEquals("",res.getStringValue()); + + assertTrue(res.isNodeSet()); + assertEquals(0,res.size()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(0,frags.getFragmentCount()); + + res.toString(); + } + + @Test + public void testNamespaceContext(){ + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + prefixes.put("","http://www.w3.org/1999/XSL/Transform"); + prefixes.put("a","urn:a"); + Saxon9XPathAdapter.NamespaceContextImpl ctx = new Saxon9XPathAdapter.NamespaceContextImpl(prefixes); + + assertEquals("http://www.w3.org/1999/XSL/Transform",ctx.getNamespaceURI("xsl")); + assertEquals("http://www.w3.org/1999/XSL/Transform",ctx.getNamespaceURI("")); + assertNotNull(ctx.getNamespaceURI("xmlns")); + assertNotNull(ctx.getNamespaceURI("xml")); + Iterator<String> it = ctx.getPrefixes("http://www.w3.org/1999/XSL/Transform"); + List<String> l = new ArrayList<String>(); + while(it.hasNext())l.add(it.next()); + assertThat(l).containsOnly("xsl",""); + assertEquals("a",ctx.getPrefix("urn:a")); + + assertEquals("",ctx.getNamespaceURI("toto")); + assertEquals(null,ctx.getPrefix("urn:toto")); + + assertEquals("xml",ctx.getPrefix("http://www.w3.org/XML/1998/namespace")); + assertEquals("xmlns",ctx.getPrefix("http://www.w3.org/2000/xmlns/")); + try{ + ctx.getNamespaceURI(null); + fail("should throw an exception"); + }catch(IllegalArgumentException iae){ + // that's expected + } + try{ + ctx.getPrefix(null); + fail("should throw an exception"); + }catch(IllegalArgumentException iae){ + // that's expected + } + } +} Property changes on: plugins/XSLT/trunk/test/xslt/Saxon9XPathAdapterTest.java ___________________________________________________________________ Added: svn:keywords + Id Author Revision Date Modified: plugins/XSLT/trunk/test/xslt/XSLTOptionPaneTest.java =================================================================== --- plugins/XSLT/trunk/test/xslt/XSLTOptionPaneTest.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/test/xslt/XSLTOptionPaneTest.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -77,7 +77,7 @@ final JPanelFixture options = optionsF.optionPane("XSLT","xslt"); Pause.pause(1000); - JTextComponentFixture factoryErrors = options.textBox(JTextComponentMatcher.withName("factory-errors")); + JTextComponentFixture factoryErrors = options.textBox(JTextComponentMatcher.withName("xslt.factory-errors")); factoryErrors.requireNotVisible().requireNotEditable(); options.comboBox("factory").selectItem(Pattern.compile(".*6.5.5.*")); Modified: plugins/XSLT/trunk/test/xslt/XSLTPluginTest.java =================================================================== --- plugins/XSLT/trunk/test/xslt/XSLTPluginTest.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/test/xslt/XSLTPluginTest.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -233,13 +233,21 @@ errorlist.close(); } - /** - * this test is failing, but it works when I do it manually... - */ - @Ignore("always failing") @Test + @Test public void testXSLTCompileOnSave() throws IOException{ File xsl = new File(testData,"broken/transform.xsl"); + /* + * the plugin must be activated manually, because : + * - it's not activated at startup because it is only activated if "compile on save" + * is checked, which is not the case by default + * - it's not activated when one of the classes of the plugin is loaded, + * since delegateFirst=true and XSLT.jar is present in the parent ClassLoader + * + * when running normally, there is no problem. + */ + jEdit.getPlugin("xslt.XSLTPlugin",true).getPluginJAR().activatePlugin(); + PluginOptionsFixture optionsF = TestUtils.pluginOptions(); JPanelFixture options = optionsF.optionPane("XSLT","xslt"); Pause.pause(1000); @@ -252,7 +260,7 @@ FrameFixture errorlist = TestUtils.findFrameByTitle("Error List"); action("save"); - Pause.pause(2000); + Pause.pause(3000); errorlist.tree().selectRow(1); assertTrue(errorlist.tree().valueAt(1).startsWith("6: (XSLT error)")); Modified: plugins/XSLT/trunk/test/xslt/XSLTPluginXPathTest.java =================================================================== --- plugins/XSLT/trunk/test/xslt/XSLTPluginXPathTest.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/test/xslt/XSLTPluginXPathTest.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -40,7 +40,11 @@ import java.io.*; import javax.swing.text.*; import javax.swing.*; +import org.gjt.sp.jedit.Buffer; +import java.util.regex.Pattern; +import org.gjt.sp.jedit.jEdit; + /** * integration tests using test_data * $Id$ @@ -53,6 +57,16 @@ TestUtils.beforeClass(); testData = new File(System.getProperty("test_data")).getCanonicalFile(); assertTrue(testData.exists()); + /* + * the plugin must be activated manually, because : + * - it's not activated at startup because it is only activated if "compile on save" + * is checked, which is not the case by default + * - it's not activated when one of the classes of the plugin is loaded, + * since delegateFirst=true and XSLT.jar is present in the parent ClassLoader + * + * when running normally, there is no problem. + */ + jEdit.getPlugin("xslt.XSLTPlugin",true).getPluginJAR().activatePlugin(); } @AfterClass @@ -93,6 +107,14 @@ File xml = new File(testData,"simple/transform.xsl"); TestUtils.openFile(xml.getPath()); + + + PluginOptionsFixture optionsF = TestUtils.pluginOptions(); + JPanelFixture options = optionsF.optionPane("XSLT","xslt"); + Pause.pause(1000); + options.comboBox("xpath-adapter").selectItem(Pattern.compile(".*XPath 1\\.0.*")); + optionsF.OK(); + action("xpath-tool-float",1); @@ -113,12 +135,237 @@ xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("//xsl:value-of"); } }); - xpathTool.button("xpath.evaluate").click(); - Pause.pause(5000); + Pause.pause(1000); xpathTool.textBox("xpath.result.data-type").requireText("node-set of size 1"); xpathTool.textBox("xpath.result.xml-fragments").requireText("<xsl:value-of select=\".\"/>\n"); xpathTool.close(); } + + @Test + public void testDocumentCache() throws IOException{ + File xml = new File(testData,"simple/source.xml"); + + TestUtils.openFile(xml.getPath()); + action("xpath-tool-float",1); + + + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.buffer").click(); + + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("/hello/text()"); + } + }); + + xpathTool.button("xpath.evaluate").click(); + + final String contents = "<?xml version=\"1.0\" ?>\n" + +"<hello>you</hello>"; + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + Buffer b = view().getBuffer(); + b.remove(0,b.getLength()); + b.insert(0,contents); + } + }); + + xpathTool.button("xpath.evaluate").click(); + + Pause.pause(1000); + xpathTool.textBox("xpath.result.value").requireText("you"); + + xpathTool.close(); + TestUtils.close(view(),view().getBuffer()); + } + + @Test + public void testFile() throws IOException{ + final File xml = new File(testData,"simple/source.xml"); + + action("xpath-tool-float",1); + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.file").click(); + + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.source.prompt").targetCastedTo(JTextComponent.class).setText(xml.getPath()); + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("/hello/text()"); + } + }); + + xpathTool.button("xpath.evaluate").click(); + + Pause.pause(1000); + xpathTool.textBox("xpath.result.value").requireText("world"); + + xpathTool.close(); + } + + @Test + public void testHighlight() + { + final File xsl = new File(testData,"simple/transform.xsl"); + + action("xpath-tool-float",1); + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.file").click(); + + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.source.prompt").targetCastedTo(JTextComponent.class).setText(xsl.getPath()); + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("//*"); + } + }); + + xpathTool.button("xpath.evaluate").click(); + + Pause.pause(1000); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(0).column(0)).click(); + assertEquals(xpathTool.textBox("xpath.result.xml-fragments").targetCastedTo(JTextArea.class).getHighlighter().getHighlights().length,1); + assertEquals(xpathTool.textBox("xpath.result.xml-fragments").targetCastedTo(JTextArea.class).getHighlighter().getHighlights()[0].getStartOffset(),0); + + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(1).column(0)).click(); + assertEquals(xpathTool.textBox("xpath.result.xml-fragments").targetCastedTo(JTextArea.class).getHighlighter().getHighlights().length,1); + assertTrue(xpathTool.textBox("xpath.result.xml-fragments").targetCastedTo(JTextArea.class).getHighlighter().getHighlights()[0].getStartOffset()>10); + + xpathTool.close(); + } + + @Test + public void testSaxon9XPathAdapter(){ + final File xsl = new File(testData,"simple/transform.xsl"); + + PluginOptionsFixture optionsF = TestUtils.pluginOptions(); + JPanelFixture options = optionsF.optionPane("XSLT","xslt"); + Pause.pause(1000); + options.comboBox("xpath-adapter").selectItem(Pattern.compile(".*XPath 2\\.0.*")); + optionsF.OK(); + + + action("xpath-tool-float",1); + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.file").click(); + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.source.prompt").targetCastedTo(JTextComponent.class).setText(xsl.getPath()); + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("(1+1,//xsl:value-of/@select)"); + } + }); + + xpathTool.button("xpath.ns.grab").click(); + Pause.pause(1000); + xpathTool.button("xpath.evaluate").click(); + + Pause.pause(1000); + xpathTool.table("xpath.result.node-set-summary").requireRowCount(2); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(0).column(0)).requireValue("xs:integer"); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(0).column(1)).requireValue(""); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(0).column(2)).requireValue("2"); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(1).column(0)).requireValue("attribute()"); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(1).column(1)).requireValue("select"); + xpathTool.table("xpath.result.node-set-summary").cell(TableCell.row(1).column(2)).requireValue("."); + + xpathTool.textBox("xpath.result.data-type").requireText("sequence of item()"); + xpathTool.textBox("xpath.result.value").requireText("2 ."); + xpathTool.textBox("xpath.result.xml-fragments").requireText("2\nselect=\".\"\n"); + + + xpathTool.close(); + + optionsF = TestUtils.pluginOptions(); + options = optionsF.optionPane("XSLT","xslt"); + Pause.pause(1000); + options.comboBox("xpath-adapter").selectItem(Pattern.compile(".*XPath 1\\.0.*")); + optionsF.OK(); + } + + @Test + public void testIncorrectDocument() throws IOException{ + File xml = new File(testData,"broken/source.xml"); + + TestUtils.openFile(xml.getPath()); + action("xpath-tool-float",1); + + + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.buffer").click(); + + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("/hello/text()"); + } + }); + + new ClickT(Option.OK).start(); + xpathTool.button("xpath.evaluate").click(); + + Pause.pause(1000); + xpathTool.close(); + } + + @Test + public void testIncorrectExpression() throws IOException{ + File xml = new File(testData,"simple/source.xml"); + + TestUtils.openFile(xml.getPath()); + action("xpath-tool-float",1); + + + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.buffer").click(); + + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("..."); + } + }); + + new ClickT(Option.OK).start(); + xpathTool.button("xpath.evaluate").click(); + + Pause.pause(1000); + xpathTool.close(); + } + + @Test + public void testDocumentDoesntExist() throws IOException{ + final File xml = new File(testData,"simple/not_there.xml"); + + action("xpath-tool-float",1); + + + final FrameFixture xpathTool = TestUtils.findFrameByTitle("XPath Tool"); + + xpathTool.radioButton("xpath.source.file").click(); + + + GuiActionRunner.execute(new GuiTask(){ + protected void executeInEDT(){ + xpathTool.textBox("xpath.source.prompt").targetCastedTo(JTextComponent.class).setText(xml.getPath()); + xpathTool.textBox("xpath.expression").targetCastedTo(JTextComponent.class).setText("..."); + } + }); + + new ClickT(Option.OK).start(); + action("xpath.evaluate"); + + Pause.pause(1000); + xpathTool.close(); + } } Modified: plugins/XSLT/trunk/test/xslt/XSLTSettingsTest.java =================================================================== --- plugins/XSLT/trunk/test/xslt/XSLTSettingsTest.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/test/xslt/XSLTSettingsTest.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -74,9 +74,9 @@ @Test public void testSaveAndLoad(){ final File xml = new File(testData,"simple/source.xml"); - final File xsl = new File(testData,"simple/transform.xml"); + final File xsl = new File(testData,"simple/transform.xsl"); File settings = new File(EditPlugin.getPluginHome(XSLTPlugin.class) - ,"source-Untitled-1-settings.xml"); + ,"source-transform-settings.xml"); if(settings.exists()) { assertTrue(settings.delete()); Added: plugins/XSLT/trunk/test/xslt/XalanXPathAdapterTest.java =================================================================== --- plugins/XSLT/trunk/test/xslt/XalanXPathAdapterTest.java (rev 0) +++ plugins/XSLT/trunk/test/xslt/XalanXPathAdapterTest.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -0,0 +1,192 @@ +/* + * XalanXPathAdapterTest.java + * :folding=explicit:collapseFolds=1: + * + * Copyright (C) 2010 Eric Le Lay + * + * The XSLT plugin is licensed under the GNU General Public License, with + * the following exception: + * + * "Permission is granted to link this code with software released under + * the Apache license version 2.0, for example used by the Xalan package." + */ +package xslt; + +// {{{ jUnit imports +import java.util.concurrent.TimeUnit; + +import org.junit.*; +import static org.junit.Assert.*; + +import org.fest.swing.fixture.*; +import org.fest.swing.core.*; +import org.fest.swing.data.TableCell; +import org.fest.swing.finder.*; +import org.fest.swing.edt.*; +import org.fest.swing.timing.*; +import org.fest.swing.core.matcher.JButtonMatcher; +import org.fest.swing.core.matcher.JTextComponentMatcher; + +import static org.fest.assertions.Assertions.*; + +import org.gjt.sp.jedit.testframework.Log; + +import static org.gjt.sp.jedit.testframework.TestUtils.*; +import static org.gjt.sp.jedit.testframework.EBFixture.*; +import org.gjt.sp.jedit.testframework.PluginOptionsFixture; +import org.gjt.sp.jedit.testframework.TestUtils; + +// }}} + +import org.gjt.sp.jedit.jEdit; +import org.gjt.sp.jedit.Buffer; + +import java.io.*; +import java.util.regex.Pattern; +import java.util.*; + +import org.w3c.dom.Document; + +/** + * unit tests of the Xalan XPath engine adapter + * $Id$ + */ +public class XalanXPathAdapterTest{ + private static File testData; + + @BeforeClass + public static void setUpjEdit() throws IOException{ + TestUtils.beforeClass(); + testData = new File(System.getProperty("test_data")).getCanonicalFile(); + assertTrue(testData.exists()); + } + + @AfterClass + public static void tearDownjEdit() { + TestUtils.afterClass(); + } + + @Test + public void testElement() throws Exception{ + final File xsl = new File(testData,"simple/transform.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + XalanXPathAdapter xpath = new XalanXPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "/xsl:stylesheet"); + + assertEquals("node-set of size 1",res.getType()); + assertThat(res.getStringValue()).contains("hello"); + + assertTrue(res.isNodeSet()); + assertEquals(1,res.size()); + + XPathAdapter.XPathNode n = res.get(0); + assertTrue(n.hasExpandedName()); + assertFalse(n.hasDomValue()); + assertEquals("element",n.getType()); + assertEquals("xsl:stylesheet",n.getName()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(1,frags.getFragmentCount()); + } + + @Test + public void testComment() throws Exception{ + final File xsl = new File(testData,"base_uri_bug/base-uri-bug.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + XalanXPathAdapter xpath = new XalanXPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "//comment()"); + + assertEquals("node-set of size 1",res.getType()); + assertThat(res.getStringValue()).contains("this stylesheet was submitted"); + + assertTrue(res.isNodeSet()); + assertEquals(1,res.size()); + + XPathAdapter.XPathNode n = res.get(0); + assertFalse(n.hasExpandedName()); + assertTrue(n.hasDomValue()); + assertThat(n.getDomValue()).contains("this stylesheet was submitted"); + assertEquals("comment",n.getType()); + assertEquals("",n.getName()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(1,frags.getFragmentCount()); + } + + @Test + public void testNumber() throws Exception{ + final File xsl = new File(testData,"simple/transform.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + XalanXPathAdapter xpath = new XalanXPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "1+1"); + + assertEquals("number",res.getType()); + assertEquals("2",res.getStringValue()); + + assertFalse(res.isNodeSet()); + assertEquals(0,res.size()); + + } + + @Test + public void testEmptySequence() throws Exception{ + final File xsl = new File(testData,"simple/transform.xsl"); + Buffer b = openFile(xsl.getPath()); + Pause.pause(1000); + Document source = DocumentCache.getFromCache(b); + + XalanXPathAdapter xpath = new XalanXPathAdapter(); + + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + + XPathAdapter.Result res = xpath.evaluateExpression(source, prefixes, "/xsl:transform"); + + assertEquals("node-set of size 0",res.getType()); + assertEquals("",res.getStringValue()); + + assertTrue(res.isNodeSet()); + assertEquals(0,res.size()); + + XMLFragmentsString frags = res.toXMLFragmentsString(); + assertEquals(0,frags.getFragmentCount()); + + res.toString(); + } + + @Test + public void testNamespaceContext(){ + Map<String,String> prefixes = new HashMap<String,String>(); + prefixes.put("xsl","http://www.w3.org/1999/XSL/Transform"); + prefixes.put("","http://www.w3.org/1999/XSL/Transform"); + prefixes.put("a","urn:a"); + XalanXPathAdapter.PrefixResolverImpl ctx = new XalanXPathAdapter.PrefixResolverImpl(prefixes); + + assertEquals("http://www.w3.org/1999/XSL/Transform",ctx.getNamespaceForPrefix("xsl")); + assertEquals("http://www.w3.org/1999/XSL/Transform",ctx.getNamespaceForPrefix("")); + assertEquals("http://www.w3.org/1999/XSL/Transform",ctx.getNamespaceForPrefix("xsl",null)); + assertNull(ctx.getBaseIdentifier()); + assertFalse(ctx.handlesNullPrefixes()); + } +} Property changes on: plugins/XSLT/trunk/test/xslt/XalanXPathAdapterTest.java ___________________________________________________________________ Added: svn:keywords + Id Author Revision Date Modified: plugins/XSLT/trunk/xslt/PropertyUtil.java =================================================================== --- plugins/XSLT/trunk/xslt/PropertyUtil.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/xslt/PropertyUtil.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -42,8 +42,8 @@ * "file.1=file1.txt", calling getEnumeratedProperty("file", properties) * would return a list containing "file0.txt" and "file1.txt". */ - public static List getEnumeratedProperty(String key) { - List values = new ArrayList(); + public static List<String> getEnumeratedProperty(String key) { + List<String> values = new ArrayList<String>(); int i = 0; String value; while ((value = jEdit.getProperty(calculateKey(key, i++))) != null) { @@ -61,13 +61,13 @@ * @param values values to be assigned to the enumerated property, in order. * All members of this List must be Strings. */ - public static void setEnumeratedProperty(String key, List values) { + public static void setEnumeratedProperty(String key, List<String> values) { List currentValues = getEnumeratedProperty(key); for (int i = 0; i < currentValues.size(); i++) { jEdit.setProperty(calculateKey(key, i), null); } for (int i = 0; i < values.size(); i++) { - jEdit.setProperty(calculateKey(key, i), (String)values.get(i)); + jEdit.setProperty(calculateKey(key, i), values.get(i)); } } Added: plugins/XSLT/trunk/xslt/Saxon9XPathAdapter.java =================================================================== --- plugins/XSLT/trunk/xslt/Saxon9XPathAdapter.java (rev 0) +++ plugins/XSLT/trunk/xslt/Saxon9XPathAdapter.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -0,0 +1,243 @@ +/* + * Saxon9XPathAdapter.java - use the XPath 2.0 Saxon engine + * + * Copyright (c) 2010 Eric Le Lay + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +package xslt; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathExpressionException; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Node; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.LinkedList; +import java.util.Iterator; +import java.util.Collections; + + +import net.sf.saxon.xpath.XPathFactoryImpl; +import net.sf.saxon.xpath.XPathExpressionImpl; +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.type.Type; +import net.sf.saxon.om.SequenceIterator; +import net.sf.saxon.om.NodeInfo; +/*import net.sf.saxon.om.GroundedIterator; +import net.sf.saxon.om.GroundedValue; +*/ +import net.sf.saxon.om.Item; +import net.sf.saxon.dom.DocumentWrapper; +import net.sf.saxon.dom.NodeWrapper; +import net.sf.saxon.dom.DOMNodeList; +import net.sf.saxon.value.SequenceExtent; +import net.sf.saxon.value.Cardinality; +import net.sf.saxon.Configuration; +import net.sf.saxon.type.TypeHierarchy; +import net.sf.saxon.type.ItemType; + +/** + * Implementation of XPathAdapter using the Saxon 9 engine + */ +public class Saxon9XPathAdapter implements XPathAdapter { + final XPathFactoryImpl factory = new XPathFactoryImpl(); + + public Result evaluateExpression(Document doc, Map<String,String> prefixes, String expression) throws XPathException,XPathExpressionException { + XPath xpath = factory.newXPath(); + xpath.setNamespaceContext(new NamespaceContextImpl(prefixes)); + + XPathExpressionImpl expr = (XPathExpressionImpl)xpath.compile(expression); + + return new SaxonResult(expr.rawIterator(new DocumentWrapper(doc,doc.getBaseURI(),expr.getConfiguration())),expr.getConfiguration()); + } + + + static class SaxonXPathNode implements XPathNode { + private Item item; + private ItemType it; + + SaxonXPathNode(Item i,TypeHierarchy hierarchy){ + this.item = i; + this.it = Type.getItemType(item,hierarchy); + } + + public boolean hasExpandedName(){ + int primitiveType=it.getPrimitiveType(); + switch(primitiveType){ + case Type.ATTRIBUTE: + case Type.ELEMENT: + case Type.FUNCTION: + case Type.NAMESPACE: + case Type.PROCESSING_INSTRUCTION: + return true; + default: + return false; + } + } + + public boolean hasDomValue(){ + switch (it.getPrimitiveType()) { + case Type.DOCUMENT: + case Type.ELEMENT: + return false; + default: + return true; + } + } + + public String getType(){ + return it.toString(); + } + + public String getName(){ + if(item instanceof NodeInfo){ + return ((NodeInfo)item).getDisplayName(); + }else { + return null; + } + } + + public String getDomValue() throws XPathException{ + return SequenceExtent.makeSequenceExtent(item.getTypedValue()).getStringValue(); + } + + } + + static class SaxonResult implements Result{ + private SequenceExtent se; + private Configuration config; + + SaxonResult(SequenceIterator si,Configuration c) throws XPathException{ + this.se = se; + this.config = c; + + SequenceExtent se = new SequenceExtent(si); + ItemType it = se.getItemType(c.getTypeHierarchy()); + } + + public String getType(){ + ItemType it = se.getItemType(config.getTypeHierarchy()); + if(se.getLength()==0) { + return "empty sequence"; + } else if(se.getLength() == 1) { + return it.toString(); + } else { + return "sequence of "+it.toString(); + } + } + + public boolean isNodeSet(){ + return true; + } + + public String getStringValue() throws XPathException{ + return se.getStringValue(); + } + + public int size(){ + return se.getLength(); + } + + public XPathNode get(int i){ + return new SaxonXPathNode(se.itemAt(i),config.getTypeHierarchy()); + } + + public XMLFragmentsString toXMLFragmentsString() throws XPathException { + XMLFragmentsString res = new XMLFragmentsString(se.getLength()); + for(int i=0;i<se.getLength();i++) { + Item it = se.itemAt(i); + if(it instanceof NodeWrapper) { + res.setNode(i,(Node)((NodeWrapper)it).getRealNode()); + } else { + res.setText(i,it.getStringValue()); + } + } + return res; + } + + public String toString(){ + return "Saxon9Adapter.Result{"+se+"}"; + } + } + + public static class NamespaceContextImpl implements NamespaceContext{ + private Map<String,String> mappings; + private Map<String,List<String>> reverseMappings; + + public NamespaceContextImpl(Map<String,String> mappings) { + this.mappings = mappings; + } + + public String getNamespaceURI(String prefix){ + if(XMLConstants.XML_NS_PREFIX.equals(prefix)) { + return XMLConstants.XML_NS_URI; + } else if(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) { + return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + } else if(mappings.containsKey(prefix)) { + return mappings.get(prefix); + } else if(prefix == null){ + throw new IllegalArgumentException("null prefix"); + } else { + return XMLConstants.NULL_NS_URI; + } + } + + public String getPrefix(String namespaceURI){ + Iterator it = getPrefixes(namespaceURI); + if(it.hasNext()) return (String)it.next(); + else return null; + } + + public Iterator getPrefixes(String namespaceURI){ + if(reverseMappings == null) { + initReverseMappings(); + } + + if(XMLConstants.XML_NS_URI.equals(namespaceURI)) { + return Collections.singletonList(XMLConstants.XML_NS_PREFIX).iterator(); + } else if(XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { + return Collections.singletonList(XMLConstants.XMLNS_ATTRIBUTE).iterator(); + } else if(reverseMappings.containsKey(namespaceURI)) { + return Collections.unmodifiableList(reverseMappings.get(namespaceURI)).iterator(); + } else if(namespaceURI == null){ + throw new IllegalArgumentException("null namespaceURI"); + } else { + return Collections.emptyList().iterator(); + } + } + + private void initReverseMappings() { + reverseMappings = new HashMap<String,List<String>>(); + for(Map.Entry<String,String> entry: mappings.entrySet()) { + List<String> l; + if(reverseMappings.containsKey(entry.getValue())) { + l = reverseMappings.get(entry.getValue()); + } else { + l = new LinkedList<String>(); + reverseMappings.put(entry.getValue(),l); + } + l.add(entry.getKey()); + } + } + } +} Property changes on: plugins/XSLT/trunk/xslt/Saxon9XPathAdapter.java ___________________________________________________________________ Added: svn:keywords + Id Author Revision Date Modified: plugins/XSLT/trunk/xslt/XMLFragmentsString.java =================================================================== --- plugins/XSLT/trunk/xslt/XMLFragmentsString.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/xslt/XMLFragmentsString.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -41,12 +41,16 @@ private static final Integer MAX_CHARS_IN_FRAGMENTS_STRING = new Integer(1000000); - private final StringBuffer buffer = new StringBuffer(""); + private final StringBuffer buffer = new StringBuffer(); /** Holds an array of the start position of each XML fragment in the fragments String */ private int[] fragmentPositions; + public XMLFragmentsString(int nodeCount) { + this.fragmentPositions = new int[nodeCount]; + } + /** * Constructs string of XML fragments representing the nodes in the node list. * @param nodelist containing nodes to be represented as XML fragments. @@ -99,6 +103,29 @@ return this.fragmentPositions.length; } + public void setNode(int index, Node node){ + if(index >= fragmentPositions.length) { + throw new IllegalArgumentException("index too big ("+index+">="+fragmentPositions.length); + } else if(fragmentPositions[index] != 0) { + throw new IllegalStateException("fragment "+index+" already initialized"); + } else { + fragmentPositions[index] = buffer.length(); + appendNode(node, 0, false); + } + } + + public void setText(int index, String value){ + if(index >= fragmentPositions.length) { + throw new IllegalArgumentException("index too big ("+index+">="+fragmentPositions.length); + } else if(fragmentPositions[index] != 0) { + throw new IllegalStateException("fragment "+index+" already initialized"); + } else { + fragmentPositions[index] = buffer.length(); + String trimmedValue = value.trim(); + buffer.append(value); + buffer.append(NL); + } + } private void appendNode(Node node, int indentLevel, boolean insideElement) { if(node != null) { Added: plugins/XSLT/trunk/xslt/XPathAdapter.java =================================================================== --- plugins/XSLT/trunk/xslt/XPathAdapter.java (rev 0) +++ plugins/XSLT/trunk/xslt/XPathAdapter.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -0,0 +1,83 @@ +/* + * XPathAdapter.java - all the operations required for the XPath tool + * + * Copyright (c) 2010 Eric Le Lay + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +package xslt; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import java.util.Map; + +/** + * interface embodying all the services required for the XPath Tool + */ +public interface XPathAdapter { + + /** + * evaluate expression against doc, given prefixes + * @param doc source document + * @param prefixes prefix->namespace bindings + * @param expression xpath expression to evaluate + * @return result of the evaluation + */ + public Result evaluateExpression(Document doc, Map<String,String> prefixes, String expression) throws Exception; + + /** + * result of an evaluation. + * Provides methods to get type, size and contents of the result. + */ + public static interface Result{ + /** @return a String description */ + public String getType() throws Exception; + /** @return is this Result a node-set */ + public boolean isNodeSet(); + /** @return the string value of the result */ + public String getStringValue() throws Exception; + /** @return number of items in the node-set/sequence */ + public int size() throws Exception; + + /** + * @param i index of the wanted item. Contrary to positions, i starts at 0 + * @return ith item of the result + */ + public XPathNode get(int i) throws Exception; + + /** + * @return an XMLFragmentsString configured to represent this result + */ + public XMLFragmentsString toXMLFragmentsString() throws Exception; + } + + /** one component of the Result, used in the Node-set summary table of the XPath tool */ + public static interface XPathNode{ + /** @return has got a name (e.g. an element has a name) */ + public boolean hasExpandedName(); + /** @return has got a value (here, an element or document don't have a value) */ + public boolean hasDomValue(); + /** @return string representation of the type of this item */ + public String getType(); + /** + * shouldn't be called if hasExpandedName() returns false ! + * @return name or empty-string.*/ + public String getName(); + /** + * @return string value of this item + */ + public String getDomValue()throws Exception; + } +} Property changes on: plugins/XSLT/trunk/xslt/XPathAdapter.java ___________________________________________________________________ Added: svn:keywords + Id Author Revision Date Deleted: plugins/XSLT/trunk/xslt/XPathNode.java =================================================================== --- plugins/XSLT/trunk/xslt/XPathNode.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/xslt/XPathNode.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -1,173 +0,0 @@ -/* - * XPathNode.java - Represents an XPath 1.0 node - * - * Copyright (c) 2002 Robert McKinnon - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -package xslt; - -import org.apache.xml.dtm.DTM; -import org.apache.xpath.NodeSetDTM; - -/** - * Represents a <a href="http://www.w3.org/TR/xpath#data-model">XPath 1.0 node</a>. - * - * @author Robert McKinnon - */ -public class XPathNode { - - private final int nodeHandle; - private final DTM dtm; - private final short nodeType; - - - /** - * Returns a XPathNode representing the node at the given index in the - * supplied node set, or null if the node at the given index is does not - * have a node type from the - * <a href="http://www.w3.org/TR/xpath#data-model">XPath 1.0 data model</a>. - * - * @return an XPathNode or null. - */ - public static XPathNode getXPathNode(NodeSetDTM nodeSet, int index) { - int nodeHandle = nodeSet.item(index); - DTM dtm = nodeSet.getDTM(nodeHandle); - short nodeType = dtm.getNodeType(nodeHandle); - - if (isXPathNodeType(nodeType)) { - return new XPathNode(nodeHandle, dtm, nodeType); - } else { - return null; - } - } - - /** - * Returns true if the node type from the - * <a href="http://www.w3.org/TR/xpath#data-model">XPath 1.0 data model</a>. - */ - private static boolean isXPathNodeType(short nodeType) { - switch (nodeType) { - case DTM.ATTRIBUTE_NODE: - case DTM.ELEMENT_NODE: - case DTM.NAMESPACE_NODE: - case DTM.PROCESSING_INSTRUCTION_NODE: - case DTM.COMMENT_NODE: - case DTM.DOCUMENT_NODE: - case DTM.TEXT_NODE: - return true; - default: - return false; - } - } - - - /** - * Constructs node with the given node type identifier. - * - * @param nodeType from {@link org.apache.xml.dtm.DTM} interface - * @throws IllegalArgumentException if nodeType is not valid. - */ - private XPathNode(int nodeHandle, DTM dtm, short nodeType) { - this.nodeHandle = nodeHandle; - this.dtm = dtm; - this.nodeType = nodeType; - } - - public boolean isElement() { - return nodeType == DTM.ELEMENT_NODE; - } - - public boolean isText() { - return nodeType == DTM.TEXT_NODE; - } - - /** - * Returns the <a href="http://www.w3.org/TR/xpath#data-model">node type</a> name. - * - * @return node type name, one of: - * root, element, text, attribute, - * processing instruction, - * namespace, or comment. - */ - public String getType() { - switch (this.nodeType) { - case DTM.ATTRIBUTE_NODE: - return "attribute"; - case DTM.COMMENT_NODE: - return "comment"; - case DTM.ELEMENT_NODE: - return "element"; - case DTM.NAMESPACE_NODE: - return "namespace"; - case DTM.PROCESSING_INSTRUCTION_NODE: - return "processing instruction"; - case DTM.TEXT_NODE: - return "text"; - default: - return "root"; - } - } - - - /** - * Returns true if the node has an - * <a href="http://www.w3.org/TR/xpath#dt-expanded-name">expanded-name</a>. - */ - public boolean hasExpandedName() { - switch (this.nodeType) { - case DTM.COMMENT_NODE: - case DTM.DOCUMENT_NODE: - case DTM.TEXT_NODE: - return false; - default: - return true; - } - } - - - /** - * There are seven XPath nodes: root, element, - * text, attribute, processing instruction, - * namespace, and comment. - */ - public boolean hasDomValue() { - switch (this.nodeType) { - case DTM.DOCUMENT_NODE: - case DTM.ELEMENT_NODE: - return false; - default: - return true; - } - } - - - public String getName() { - return this.dtm.getNodeNameX(this.nodeHandle); - } - - - public String getDomValue() { - String domValue = this.dtm.getNodeValue(this.nodeHandle); - - if (hasDomValue()) { - domValue = XSLTUtilities.removeIn(domValue, (char) 10); //remove '\r' to temporarily fix a bug in the display of results in Windows - } - - return domValue; - } - -} Modified: plugins/XSLT/trunk/xslt/XPathTool.java =================================================================== --- plugins/XSLT/trunk/xslt/XPathTool.java 2010-03-12 06:15:33 UTC (rev 17458) +++ plugins/XSLT/trunk/xslt/XPathTool.java 2010-03-13 13:20:20 UTC (rev 17459) @@ -112,6 +112,8 @@ public class XPathTool extends JPanel implements ListSelectionListener, ActionListener, DefaultFocusComponent, ItemListener { + public static final String XPATH_ADAPTER_PROP="xpath.adapter"; + private View view; private final XsltAction grabNSAction = new GrabNSAction(); private final BufferOrFileVFSSelector inputSelectionPanel; @@ -125,8 +127,8 @@ private JPanel dataTypePanel; private boolean autoCompleteEnabled; + private XPathAdapter adapter; - public XPathTool(View view) { super(new GridBagLayout()); this.view = view; @@ -214,6 +216,22 @@ } + private XPathAdapter getXPath() { + String xpath = jEdit.getProperty(XPATH_ADAPTER_PROP); + if(adapter == null || !adapter.getClass().getName().equals(xpath)) { + try { + adapter = (XPathAdapter)Class.forName(xpath).newInstance(); + } catch(ClassNotFoundException e) { + XSLTPlugin.processException(e,"error instantiating XPath engine",this); + } catch(InstantiationException e) { + XSLTPlugin.processException(e,"error instantiating XPath engine",this); + } catch(IllegalAccessException e) { + XSLTPlugin.processException(e,"error instantiating XPath engine",this); + } + } + return adapter; + } + public void actionPerformed(ActionEvent event) { if(!inputSelectionPanel.isSourceFileDefined()) { GUIUtilities.message(this,"xpath.error.no-source",new Object[]{}); @@ -255,23 +273,18 @@ String expression = expressionPanel.getExpression(); - /* don't know how to get the result type using javax.xml.xpath.* API. - * Plus here, using NODESET will throw an exception when evaluating 1+1 - XPathFactory factory = XPathFactory.newInstance(); - XPath xpath = factory.newXPath(); - - Object result = xpath.evaluate(expression, document,XPathConstants.NODESET); - System.err.println(result);*/ - - PrefixResolverImpl res = new PrefixResolverImpl(nsPanel.getMap()); - XObject xObject = XPathAPI.eval(document, expression, res); - expressionPanel.addToHistory(expression); - - dateTypeField.setText(getDataTypeMessage(xObject)); - xObject.xstr().toString(); - setResultValue(xObject, document, expression); - setNodeSetResults(xObject); - setXmlFragments(xObject); + XPathAdapter xpath = getXPath(); + if(xpath != null) { + XPathAdapter.Result result = xpath.evaluateExpression(document,nsPanel.getMap(),expression); + Log.log(Log.DEBUG,this,"evaluateExpression returns : "+result); + + expressionPanel.addToHistory(expression); + + dateTypeField.setText(result.getType()); + setResultValue(result); + setNodeSetResults(result); + setXmlFragments(result); + } } @@ -290,60 +303,30 @@ return splitPane; } - - /** - * Returns a message containing the data type selected by the XPath expression. - * Note: there are four data types in the XPath 1.0 data model: node-set, string, - * number, and boolean. - * - * @param xObject XObject to be converted - * @return string describing the selected data type - */ - private String getDataTypeMessage(XObject xObject) throws TransformerException { - String typeMessage = null; - - if (xObject.getType() == XObject.CLASS_NODESET) { - NodeSetDTM nodeSet = xObject.mutableNodeset(); - - Object[] messageArgs = new Object[]{new Integer(nodeSet.size())}; - typeMessage = MessageFormat.format(jEdit.getProperty("xpath.result.data-type.node-set"), messageArgs); - } else { - Object[] messageArgs = new Object[]{xObject.getTypeString().substring(1).toLowerCase()}; - typeMessage = MessageFormat.format(jEdit.getProperty("xpath.result.data-type.not-node-set"), messageArgs); - } - - return typeMessage; - } - - - private void setResultValue(XObject xObject, final Document document, final String expression) { - final boolean isNodeSet = isNodeSet(xObject); - final String text = xObject.xstr().toString(); - + private void setResultValue(f... [truncated message content] |