/sublime-xpath

Sublime Text plugin for easier cursor navigation of XML and HTML files using XPath 1.0.

Primary LanguagePython

Sublime Text - XPath Plugin

Features:

  • Updates status bar text to XPath of first selection.
  • Copy XPath at cursor(s) to clipboard.
  • Jump selection to relative tag - previous or next sibling, parent, or self. Why "self", you might ask? Because it is also possible to select the open tag, the close tag, both the opening and closing tag, the attributes in the open tag, and the entire tag contents - optionally including the tag itself. This works for multiple selections as well, of course.
  • Query XML and (X)HTML documents by XPath 1.0 expression.
    • with syntax highlighting and intelligent auto-completion.
    • with a custom print function that can be used as a debugging aid by logging nodesets etc. to the console.
    • display results in real-time (i.e. as you type the query, fitting in perfectly with Sublime's other actions). (With an option to customize this, if desired.)
    • move the cursor to the highlighted result.
    • reference multiple context nodes (at cursor positions) by using the $contexts variable.
    • Execute a query and select all the corresponding nodes in the document. (There is an entry in the command palette to re-run the previous query and select all results, but please note that it doesn't preserve the context nodes at the moment.)
    • with history, optionally globally or per document.
    • optionally normalize whitespace when displaying text results (via a setting).
    • define custom variables in the settings file.
  • Show XML well-formedness parse errors, and move the cursor to the location where the error occurred.
  • Tidy HTML or "tag soup" into valid XML.

Settings:

See default settings for details and default values.

  • show_hierarchy_only - Whether to show only hierarchy in status bar, instead of exact xpath. i.e. /Root/Node instead of /Root/Node[3]
  • show_all_attributes - Whether to show all attributes in the path. If false, will use a provided whitelist.
  • case_sensitive - Whether to ignore case when determining tag index and whether an attribute matches one defined in the whitelist. Ignored for when querying an xpath.
  • copy_unique_path_only - Whether to copy only unique xpaths to the clipboard when there are multiple selections.
  • attributes_to_include - Specific attributes or namespaces to include in the XPath.
  • show_attributes_in_hierarchy - Whether or not to include attributes when in hierarchy mode. (If show_all_attributes is false and the attributes_to_include whitelist is empty, this will have no effect.)
  • live_mode - whether to show the results of the xpath query while it is being typed. If false, will only show the results after the user presses enter in the input box.
  • default_namespace_prefix - the prefix to use when the xml document contains a default namespace with no prefix. e.g. <test xmlns="http://uri/"> XPath 1.0 doesn't support blank prefixes, so, for convenience, this plugin can set one for you.
  • show_namespace_prefixes_from_query - in case of blank namespace prefixes (see default_namespace_prefix) or multiple namespace URIs being referenced from the same prefix, the plugin will automatically make them unique, so that you can easily use them in a query. If this is turned on, the xpaths that are shown in the status bar and copied to the clipboard will be directly queryable by this plugin. If this is turned off, element names in the path will reflect those in the source document.
  • only_show_xpath_if_saved - whether or not to only show the current xpath in the status bar if the view is not dirty. This could be useful to save wasting CPU cycles (from constant parsing) when editing a document, for example.
  • max_results_to_show - the maximum number of results to show from the xpath query. Set to <= 0 for no limit. Useful to speed up display of results when there are lots.
  • normalize_whitespace_in_preview - whether or not to normalize whitespace for text results in the preview. Defaults to false, because there are situations when it is important to see exact results.
  • variables - a dictionary of custom variables, which can be used when writing an XPath query expression.
  • auto_completion_triggers - characters that, when typed while entering an XPath expression, will automatically show autocompletions. If empty, autocompletion can still be triggered manually.
  • intelligent_auto_complete - whether or not to include intelligent autocompletion suggestions from the document.
  • goto_element - when an element is selected via an XPath query, which aspect of it the cursor should move to. Possible values are:
    • open - Select the name of the element in the open tag.
    • close - Select the name of the element in the close tag.
    • names - Select the name of the element in both the open and the close tag.
    • open_attributes - Select all the attributes in the open tag.
    • content - Select the content of the element.
    • entire - Select the entire element i.e. it's open tag, contents and close tag.
    • none - Do not move the cursor.
  • goto_attribute - when an attribute is selected via an XPath query, which aspect of it the cursor should move to. Possible values are:
    • name - Select the name of the attribute.
    • value - Select the value (inside the quotes) of the attribute.
    • entire - Select the name and the value of the attribute.
    • element - Select the element that the attribute belongs to, using the goto_element rules.
    • none - Do not move the cursor.
  • sgml_selector - a scope selector to determine what to parse as XML and enable XPath functions for. Defaults to HTML and XML, excluding things like ASP and PHP.
  • show_xml_parser_errors - whether or not errors encountered while parsing the document should be shown in the status bar. Disable it if you have other plugins that also show XML parsing/validation errors.

No key bindings are set by default, but an example sublime-keymap file is included, to show the available commands and arguments. See this documentation for more details about keybindings in ST3.

Demonstrations

  • Autocompletion in action Autocompletion in action
  • Move cursor to a single highlighted result Move cursor to result
  • Example usage of selecting all the results of the previous XPath query Move cursor
  • Copying the XPath(s) of the node(s) under the cursor(s) to the clipboard Copy XPath to clipboard
  • Working with multiple context nodes Multiple context nodes
  • Clean badly formed HTML / tag soup Clean tag soup

Installation

The recommended way to install the Sublime Text XPath plugin is via Package Control. Package Control will install the plugin on your system and keep it up to date.

  1. Ensure Package Control is installed.
  2. In Sublime Text, open the Preferences menu, and select Package Control.
  3. Select Package Control: Install Package.
  4. Start typing xpath. When you see it, select it.
  5. Wait for it to install.
  6. Restart Sublime Text to be sure everything is loaded properly.
  7. Enjoy!

Troubleshooting

CDATA Nodes

When working with XML documents, you are probably used to the Document Object Model (DOM), where CDATA nodes are separate to text nodes. XPath sees text() nodes as all adjacent CDATA and text node siblings together. If you really need to work with separate text and CDATA nodes in XPath, you will need to ensure that an XML comment separates the nodes in the source document.

Example:

<hello><![CDATA[world]]>foobar</hello>
<hello><![CDATA[world]]><!-- separator, so that the CDATA and text nodes are non-adjacent -->foobar</hello>

The XPath /hello[1]/text() on the first example will return a single text node: worldfoobar. On the second example, it will return two text nodes: world and foobar. More information can be found at this Stack Overflow Q&A.

Namespaces

XPath 1.0 does not have the concept of a default namespace. Therefore, if a node in the XML document being queried defines a default namespace, that namespace should be mapped to a prefix in the XPath query expression for easier access. This plugin will do that for you automatically. See the included example_xml_ns.xml file for more details.

Nodes before the root element

Note that due to the way ElementTree (the Python XML module) works, comments, processing instructions or doctypes that come before the root node of the document won't be navigatable by this plugin.

Potential future improvements:

Feature requests, bug reports/fixes and usability suggestions are always welcome.

In no particular order, here are some ideas of how this plugin could be made even more awesome:

  • Optimize for when modifications to the underlying XML document are made by the user, especially changes that don't alter the document structure. Currently, the whole document is re-parsed on every tiny little change (i.e. every character press while typing). (although many changes in quick succession means it will abort an in-progress parse to start again with the latest changes included.)
  • Integrate with the awesome BracketHighlighter plugin? For efficiency - as we have already stored the location of each tag - and it will get round the large distance between tags limitation that BH has. It could also remove some duplicate navigation functionality when both plugins are installed.
  • Allow defining custom XPath functions in the sublime-settings file.
  • Allow defining variables as (absolute) XPath expressions that would get evaluated into a nodeset.

Contributors

  • Ross Hadden (@rosshadden)
  • Keith Hall (@keith-hall)
  • @BrutalSimplicity