You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlbeans.apache.org by ra...@apache.org on 2009/02/04 01:59:29 UTC
svn commit: r740542 - in /xmlbeans/trunk/samples/XmlSort: ./ src/ src/org/
src/org/apache/ src/org/apache/xmlbeans/ src/org/apache/xmlbeans/samples/
src/org/apache/xmlbeans/samples/cursor/ xml/
Author: radup
Date: Wed Feb 4 00:59:29 2009
New Revision: 740542
URL: http://svn.apache.org/viewvc?rev=740542&view=rev
Log:
Added sample showing how to order a set of elements using XmlCursor.
Added:
xmlbeans/trunk/samples/XmlSort/
xmlbeans/trunk/samples/XmlSort/README.txt
xmlbeans/trunk/samples/XmlSort/build.xml
xmlbeans/trunk/samples/XmlSort/src/
xmlbeans/trunk/samples/XmlSort/src/org/
xmlbeans/trunk/samples/XmlSort/src/org/apache/
xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/
xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/
xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/cursor/
xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/cursor/XmlSort.java
xmlbeans/trunk/samples/XmlSort/xml/
xmlbeans/trunk/samples/XmlSort/xml/unsorted.xml
Added: xmlbeans/trunk/samples/XmlSort/README.txt
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/samples/XmlSort/README.txt?rev=740542&view=auto
==============================================================================
--- xmlbeans/trunk/samples/XmlSort/README.txt (added)
+++ xmlbeans/trunk/samples/XmlSort/README.txt Wed Feb 4 00:59:29 2009
@@ -0,0 +1,51 @@
+Sample: XmlSort
+Category: cursor sample
+Author: Radu Preotiuc-Pietro
+Last Updated: Feb. 3, 2009
+
+Versions:
+ xmlbeans-v2
+
+-----------------------------------------------------------------------------
+
+This is another practical sample on how to use XmlCursor. It sorts all the
+children elements of a given parent in (reverse) alphabetical order. It uses
+insertion sort to minimize the number of swaps (and because it is stable) and
+XmlCursor.moveXml() to perform the swaps.
+
+The algorithm works by conceptually separating the list of children into a
+sorted list and an unsorted list. Each list is represented by an XmlCursor
+positioned at the head of the list. At the beginning, the sorted list
+contains the first child and the unsorted list contains the rest of the
+children (if any). Then, each of the elements in the unsorted list is
+inserted in the already-sorted list in its appropriate place using the
+moveXml() method (the text following each element is then moved along with
+the element).
+
+To build this sample, call 'ant build' and to run it against the provided
+sample XML file, call 'ant run'.
+
+To run the sample from the command line using 'java', provide as the first
+parameter the name of the XML file to process and as the second argument
+(optional), an XPath pointing to the element whose children are to be sorted
+(by default, the children of the root element are sorted). The XPath must
+evaluate to an element and one element only, otherwise an error will be
+reported. The console output will mirror the input file, with the children
+of the given element sorted in ascending alphabetical order.
+
+This sample can also be used as a library routine by calling its main
+static method: XmlSort.sort(XmlObject, Comparator). The XmlObject whose
+children are to be sorted is passed directly as a parameter and the
+Comparator defines the order in which the elements are to be sorted. The
+parameters to the compare() method are two XmlCursors pointing to the
+two elements to be compared. The inner class XmlSort.QNameComparator
+implements comparison based on the QName of the elements (ascending or
+descending) but custom comparison methods (based for instance on the
+value of some attribute etc) can also be passed in.
+
+To try out this sample:
+
+1. Set XMLBEANS_HOME in your environment
+2. Ant must be on your PATH
+3. To compile the sample source, run "ant build"
+4. To execute the sample, run "ant run"
Added: xmlbeans/trunk/samples/XmlSort/build.xml
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/samples/XmlSort/build.xml?rev=740542&view=auto
==============================================================================
--- xmlbeans/trunk/samples/XmlSort/build.xml (added)
+++ xmlbeans/trunk/samples/XmlSort/build.xml Wed Feb 4 00:59:29 2009
@@ -0,0 +1,96 @@
+<!--
+Copyright 2004 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+<project name="XmlSort" default="build">
+
+ <property environment="env"/>
+
+ <path id="XmlSort.path">
+ <path refid="xmlbeans.path"/>
+ <pathelement path="build/classes"/>
+ </path>
+
+ <target name="init">
+ <property name="xmlbeans.home" value="${env.XMLBEANS_HOME}"/>
+ <echo message="xmlbeans.home: ${xmlbeans.home}"/>
+
+ <!-- check for xbean.jar from binary distribution -->
+ <available
+ property="xmlbeans.lib"
+ value="${xmlbeans.home}/lib"
+ file="${xmlbeans.home}/lib/xbean.jar" />
+
+ <!-- check for xbean.jar compiled from source -->
+ <available
+ property="xmlbeans.lib"
+ value="${xmlbeans.home}/build/lib"
+ file="${xmlbeans.home}/build/lib/xbean.jar" />
+
+ <fail message="Set XMLBEANS_HOME in your enviornment."
+ unless="xmlbeans.lib"/>
+
+ <echo message="xmlbeans.lib: ${xmlbeans.lib}"/>
+ <path id="xmlbeans.path">
+ <fileset dir="${xmlbeans.lib}" includes="*.jar"/>
+ </path>
+ </target>
+
+ <!-- ========================== clean ==== -->
+
+ <target name="clean">
+ <delete dir="build"/>
+ </target>
+
+ <!-- ========================== build ==== -->
+
+ <target name="build" depends="init,XmlSort.classes">
+ </target>
+
+ <target name="XmlSort.classes" depends="init">
+ <mkdir dir="build/classes"/>
+
+ <javac srcdir="src"
+ destdir="build/classes"
+ classpathref="XmlSort.path"
+ debug="on"
+ source="1.4"
+ />
+ </target>
+
+ <!-- ========================== run ==== -->
+
+ <target name="run" depends="init,build">
+ <echo message="============================== running XmlSort"/>
+ <java
+ classname="org.apache.xmlbeans.samples.cursor.XmlSort"
+ classpathref="XmlSort.path"
+ fork="true">
+ <arg line="xml/unsorted.xml"/>
+ </java>
+ </target>
+
+ <!-- ========================== test ==== -->
+
+ <target name="test" depends="init,build">
+ <echo message="============================== testing XmlSort"/>
+ <java
+ classname="org.apache.xmlbeans.samples.cursor.XmlSort"
+ classpathref="XmlSort.path"
+ fork="true">
+ <arg line="xml/unsorted.xml"/>
+ </java>
+ </target>
+
+</project>
Added: xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/cursor/XmlSort.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/cursor/XmlSort.java?rev=740542&view=auto
==============================================================================
--- xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/cursor/XmlSort.java (added)
+++ xmlbeans/trunk/samples/XmlSort/src/org/apache/xmlbeans/samples/cursor/XmlSort.java Wed Feb 4 00:59:29 2009
@@ -0,0 +1,219 @@
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xmlbeans.samples.cursor;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Comparator;
+
+import org.apache.xmlbeans.XmlCursor;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+
+import javax.xml.namespace.QName;
+
+/**
+ */
+public final class XmlSort
+{
+ /**
+ * Receives an XML element instance and sorts the children of this
+ * element in lexicographical (by default) order.
+ *
+ * @param args An array in which the first item is a
+ * path to the XML instance file and the second item (optional) is
+ * an XPath inside the document identifying the element to be sorted
+ */
+ public static void main(String[] args)
+ {
+ if (args.length < 1 || args.length > 2)
+ {
+ System.out.println(" java XmlSort <XML_File> [<XPath>]");
+ return;
+ }
+ File f = new File(args[0]);
+ try
+ {
+ XmlObject docInstance = XmlObject.Factory.parse(f);
+ XmlObject element = null;
+ if (args.length > 1)
+ {
+ String xpath = args[1];
+ XmlObject[] result = docInstance.selectPath(xpath);
+ if (result.length == 0)
+ {
+ System.out.println("ERROR: XPath \"" + xpath + "\" did not return any results");
+ }
+ else if (result.length > 1)
+ {
+ System.out.println("ERROR: XPath \"" + xpath + "\" returned more than one " +
+ "node (" + result.length + ")");
+ }
+ else
+ element = result[0];
+ }
+ else
+ {
+ // Navigate to the root element
+ XmlCursor c = docInstance.newCursor();
+ c.toFirstChild();
+ element = c.getObject();
+ c.dispose();
+ }
+ if (element != null)
+ sort(element, new QNameComparator(QNameComparator.ASCENDING));
+ System.out.println(docInstance.xmlText());
+ }
+ catch (IOException ioe)
+ {
+ System.out.println("ERROR: Could not open file: \"" + args[0] + "\": " +
+ ioe.getMessage());
+ }
+ catch (XmlException xe)
+ {
+ System.out.println("ERROR: Could not parse file: \"" + args[0] + "\": " +
+ xe.getMessage());
+ }
+ }
+
+ /**
+ * Sorts the children of <code>element</code> according to the order indicated by the
+ * comparator.
+ * @param element the element whose content is to be sorted. Only element children are sorted,
+ * attributes are not touched. When elements are reordered, all the text, comments and PIs
+ * follow the element that they come immediately after.
+ * @param comp a comparator that is to be used when comparing the <code>QName</code>s of two
+ * elements. See {@link org.apache.xmlbeans.samples.cursor.XmlSort.QNameComparator} for a simple
+ * implementation that compares two elements based on the value of their QName, but more
+ * complicated implementations are possible, for instance, ones that compare two elements based
+ * on the value of a specifc attribute etc.
+ * @throws IllegalArgumentException if the input <code>XmlObject</code> does not represent
+ * an element
+ */
+ public static void sort(XmlObject element, Comparator comp)
+ {
+ XmlCursor headCursor = element.newCursor();
+ if (!headCursor.isStart())
+ throw new IllegalStateException("The element parameter must point to a STARTDOC");
+ // We use insertion sort to minimize the number of swaps, because each swap means
+ // moving a part of the document
+ /* headCursor points to the beginning of the list of the already sorted items and
+ listCursor points to the beginning of the list of unsorted items
+ At the beginning, headCursor points to the first element and listCursor points to the
+ second element. The algorithm ends when listCursor cannot be moved to the "next"
+ element in the unsorted list, i.e. the unsorted list becomes empty */
+ boolean moved = headCursor.toFirstChild();
+ if (!moved)
+ {
+ // Cursor was not moved, which means that the given element has no children and
+ // therefore there is nothing to sort
+ return;
+ }
+ XmlCursor listCursor = headCursor.newCursor();
+ boolean moreElements = listCursor.toNextSibling();
+ while (moreElements)
+ {
+ moved = false;
+ // While we can move the head of the unsorted list, it means that there are still
+ // items (elements) that need to be sorted
+ while (headCursor.comparePosition(listCursor) < 0)
+ {
+ if (comp.compare(headCursor, listCursor) > 0)
+ {
+ // We have found the position in the sorted list, insert the element and the
+ // text following the element in the current position
+ /*
+ * Uncomment this code to cause the text before the element to move along
+ * with the element, rather than the text after the element. Notice that this
+ * is more difficult to do, because the cursor's "type" refers to the position
+ * to the right of the cursor, so to get the type of the token to the left, the
+ * cursor needs to be first moved to the left (previous token)
+ *
+ headCursor.toPrevToken();
+ while (headCursor.isComment() || headCursor.isProcinst() || headCursor.isText())
+ headCursor.toPrevToken();
+ headCursor.toNextToken();
+ listCursor.toPrevToken();
+ while (listCursor.isComment() || listCursor.isProcinst() || listCursor.isText())
+ listCursor.toPrevToken();
+ listCursor.toNextToken();
+ while (!listCursor.isStart())
+ listCursor.moveXml(headCursor);
+ listCursor.moveXml(headCursor);
+ */
+ // Move the element
+ listCursor.moveXml(headCursor);
+ // Move the text following the element
+ while (!listCursor.isStart() && !listCursor.isEnd())
+ listCursor.moveXml(headCursor);
+ moreElements = listCursor.isStart();
+ moved = true;
+ break;
+ }
+ headCursor.toNextSibling();
+ }
+ if (!moved)
+ {
+ // Because during the move of a fragment of XML, the listCursor is also moved, in
+ // case we didn't need to move XML (the new element to be inserted happened to
+ // be the last one in order), we need to move this cursor
+ moreElements = listCursor.toNextSibling();
+ }
+ // Reposition the head of the sorted list
+ headCursor.toParent();
+ headCursor.toFirstChild();
+ }
+ }
+
+ /**
+ * Implements a <code>java.util.Comparator</code> for comparing <code>QName</code>values.
+ * The namespace URIs are compared first and if they are equal, the local parts are compared.
+ * <p/>
+ * The constructor accepts an argument indicating whether the comparison order is the same as
+ * the lexicographic order of the strings or the reverse.
+ */
+ public static final class QNameComparator implements Comparator
+ {
+ public static final int ASCENDING = 1;
+ public static final int DESCENDING = 2;
+
+ private int order;
+
+ public QNameComparator(int order)
+ {
+ this.order = order;
+ if (order != ASCENDING && order != DESCENDING)
+ throw new IllegalArgumentException("Please specify one of ASCENDING or DESCENDING "+
+ "comparison orders");
+ }
+
+ public int compare(Object o, Object o1)
+ {
+ XmlCursor cursor1 = (XmlCursor) o;
+ XmlCursor cursor2 = (XmlCursor) o1;
+ QName qname1 = cursor1.getName();
+ QName qname2 = cursor2.getName();
+ int qnameComparisonRes = qname1.getNamespaceURI().compareTo(qname2.getNamespaceURI());
+ if (qnameComparisonRes == 0)
+ return order == ASCENDING ?
+ qname1.getLocalPart().compareTo(qname2.getLocalPart()) :
+ -qname1.getLocalPart().compareTo(qname2.getLocalPart());
+ else
+ return order == ASCENDING ? qnameComparisonRes : -qnameComparisonRes;
+ }
+ }
+}
+
\ No newline at end of file
Added: xmlbeans/trunk/samples/XmlSort/xml/unsorted.xml
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/samples/XmlSort/xml/unsorted.xml?rev=740542&view=auto
==============================================================================
--- xmlbeans/trunk/samples/XmlSort/xml/unsorted.xml (added)
+++ xmlbeans/trunk/samples/XmlSort/xml/unsorted.xml Wed Feb 4 00:59:29 2009
@@ -0,0 +1,22 @@
+<!--
+Copyright 2004 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+<root>
+ <bravo>bravo</bravo>
+ <charlie>charlie1</charlie>
+ <alpha>alpha</alpha>
+ <delta>delta</delta>
+ <charlie>charlie2</charlie>
+</root>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: commits-help@xmlbeans.apache.org