This is the README file for Excelsior! Path. Click here to download Excelsior! Path now.
Excelsior! Path is an XPath implementation for Cocoa. It requires the Excelsior! framework.
Here are some of the reasons why Excelsior! Path was created.
This is a preview release. There are still bugs and some functionality is missing. Only downoad Excelsior! Path if you want to see the code or want to help with testing or development.
Here's an example of how to use the Excelsior! Path framework.
// assume this exists
NSURL *url;
NSString *path = @"//a[@id='36']";
PathExpression *expression = [PathExpression expressionWithString:path];
XMLKeyValueElement *xml = [XMLKeyValueElement elementWithDataFromURL:url];
id result = [expression evaluateWithElement:xml];
In summary, create a PathExpression object from a valid XPath string, then evaluate it against an XMLKeyValueElement object to get the results.
The result of evaluating a PathExpression can be an NSString, NSNumber, NSArray, or PathBoolean, corresponding to the XPath types string, number, nodeset, and boolean. If an NSArray is the result, it will contain zero or more XMLKeyValueElements.
Here is a brief overview of the classes in Excelsior! Path.
A PathExpression, or parsed XPath, is represented as a tree. PathExpression extends JMRTree from the Excelsior! framework.
Generally, a PathExpression is parsed from an XPath string by
The information specific to an XPath tree or subtree is stored in the PathExpression's node, which is either a PathNode or a PathSegmentNode. A PathNode can contain an operator type, a string or number value, or a function selector. Which of these values are used depends on the operator type. PathSegmentNode extends PathNode and represents a path segment. In addition to the PathNode values, a PathSegmentNode can contain an axis, a node test, and a namespace prefix.
XMLAttribute is necessary because XPath requires that attributes can be iterated over and returned as values in a node set. Attributes of an XMLKeyValueElement are represented as a dictionary mapping attribute keys to attribute values. An XMLAttribute is an object representing an attribute, allowing attributes to be treated like other XML nodes.
Similarly, a PathBoolean is an object that allows boolean values to be returned as the result of a evaluating an XPath expression.
A PathIterator returns nodes (elements or attributes) in an order determined by an XPath axis. (See the PathAxis enumeration in PathIterator.h for a list of possible axes.) A PathIterator must be initialized with an axis value and an element from which it will start it's iteration. Successive calls to nextElement returns successive nodes, finally returning nil when nodes for the axis have been exhausted.
When a function is parsed in an XPath expression, it is represented as a selector. The selector is constructed by appending a ":" for each function argument to the function name, then converting the resulting string to a selector. When the expression is evaluated, the PathExpression tries to execute a method corresponding to the function selector. The expressions representing the function arguments are evaluated, and the results are submitted as the arguments to the method.
Of course, this requires that any functions used in an XPath expression have a corresponding method implemented in PathExpression. A benefit of this approach is that it should be possible to extend the available functions by simply implementing a category on PathExpression with the corresponding method signatures. A weakness of this approach is that it does not support XPath functions with an unlimited number of arguments. A solution to this problem remains to be designed and implemented.
As of now, the methods for the following functions have been implemented.
Probably the most important and pressing need is a more complete test suite. Excelsior! Path won't be very useful unless it behaves the same as other accepted XPath implementations, and adheres as closely to the XPath specification as possible. If you want to help with XPath, providing test cases is one of the best ways you can do that.
In the meantime, I plan to compare ExcelsiorPath's output to the output of the libxml XPath implementation, using the xml files and XPath expressions from the libxml test suite. The challenge will be comparing the XML node results in a canonical fashion, ignoring extraneous whitespace, etc. This is currently my highest priority for this project.
Another need is to complete the implementation of PathExpression methods for XPath functions (see Functions above). My current goal is to complete the implementation of the functions in the w3c Core Function Library
After these items are completed, my goal will be to expand the conformance tests to garuntee as much compliance with the w3c specifications as possible.
To build Excelsior! Path, you first need to build Excelsior!. After building the ExcelsiorFramework target in the Excelsior project, copy ExcelsiorFramework.framework from the Excelsior build directory to /Library/Frameworks/ExcelsiorFramework.framework (you will need to authenticate as an administrator to do this).
Alternatively, if you want ExcelsiorFramework in a different location, you can edit the path for ExcelsiorFramework in the ExcelsiorPath project. Under the ExcelsiorPath project icon in the Groups and Files column, select External Frameworks and Libraries > Other Frameworks > ExcelsiorFramework.framework, then click the inspector icon on the toolbar (the i in the blue circle). Click Choose... then navigate to where ExcelsiorFramework.framework is located.
If you want to run the Excelsior! Path tests, you need OCUnit. Look here for more information.
Prebinding a library or framework allows applications built with the framework to launch faster. To enable prebinding, the ExcelsiorPath framework is built with a preferred first segment load address of 0xb0000000. This should avoid conflict with the load address of any application using it (0x00000000). If this conflicts with the memory space of any other library used by your application, change this value to something that does not conflict before building the framework. For more information about prebinding see this note.
Prebinding is enabled only for the Deployment build style.
This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
A copy of this license is also included in the Documentation folder of this project, in the file AttributionLicense.html.
In summary, this license stipulates that anyone who distributes this work or a derivative of this work must credit the original author (Jim Rankin), in a reasonable fashion. One way to satisfy this requirement would be to include the following in a text or HTML file distributed with the derivative work.
"This program uses the Excelsior! Path class library created by Jim Rankin. For more information about Excelsior! Path, email jimbokun@mac.com."
Send comments, complaints, suggestions, fixes and praise to jimbokun@mac.com