Netbeans IDE has a dynamic code completion feature, that allows user to pick items from a list of relevant items in a given context. While you're in the editor, you can either press Ctrl+Space or as you type in characters, the IDE offers code completion. This is very helpful and lets user concentrate on his/her work, rather than figuring out what to type next. This feature is available on Java files, HTML files, JSP files, ANT build scripts and some custom XML files.
Netbeans 6.0 extends this feature and offers code completion on XML documents that are constrained by XML schemas. Here is an sample XML document that is constrained by the schema PO.xsd:
<po:purchaseOrder xmlns:po="http://xml.netbeans.org/schema/PO" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml.netbeans.org/schema/PO http://xml.netbeans.org/schema/PO.xsd"> ..... </po:purchaseOrder>
Element Code Completion
When the user types in a start tag < inside an existing element, she/he will see a list of child elements for that parent element. For example when you're inside purchaseOrder element and you start typing in the start tag <, you'll see all child elements of purchaseOrder
Attribute Code Completion
When the user types in a Space character inside the element tag, IDE offers a list of attributues for that element. For example when you're inside the shipTo element and you'll see all attributes for shipTo as follows:
For each selected item in the completion list, IDE offers documentation as you can see from the pictures above. The documentation is self explanatory, however there are few points worth mentioning:
- The documentation text comes from schema annotation for that item in the schema.
- Mandatory items appears as bold in the documentation pane.
- For an element, children elements are displayed along with their cardinality information.
- For an attribute, its data type is displayed.
Which schema to use?
The IDE allows you to have your schemas anywhere.
- Local: You can keep your schemas locally in the same project. Instance document must mention this location either as an absolute or relative path.
- Runtime Catalog: You can register your schemas in the IDE's catalog. The system ID must match the location in the instance document.
- Internet: You can have your schemas anywhere in the internet. The instance document must mention the location as the schema's URI.
How it works?
schemaLocation and noNamespaceSchemaLocation
An XML instance document that conforms to a schema must mention about the schema with the help of schemaLocation or noNamespaceSchemaLocation attribute at the root element of the document. The schemaLocation and noNamespaceSchemaLocation attributes can be used in a document to provide hints to find the physical location of schema documents which may be used for assessment and validation.
The value of schemaLocation consists of one or more pairs of URI references, separated by white space. The first member of each pair is a namespace name, and the second member of the pair is a hint describing where to find an appropriate schema document for that namespace. Where as, the value of noNamespaceSchemaLocation consists of one or more schemas separated by white space. Typically, schemaLocation is used for schemas with a target namespace and noNamespaceSchemaLocation is used for schemas with no target namespace.
XML Schema defines the structure of an instance documents. A schema can have one or more top level elements. An instance document can be created with any one top level element from the schema. In the example above, we have used purchaseOrder element as the document's root element.
As a general rule, if the root element provides necessary hints as to where to find the schemas and if certain conditions are met, the IDE will be able to offer code completion as per the schema(s). The IDE first tries to find the schema in the local file system. If not found, it looks up the runtime catalog. If the schema is not found anywhare, it'll not offer any code completion help.
In order to get code completion in an instance document, one of the following conditions must be met:
- If the root element is namespace-qualified, the namespace of the document must match the target namespace of one schema specified in the schemaLocation attribute. The schema that matches, is said to be the primary schema. The primary schema must have a root element with the same name as the root element of the instance document.
- If the root element is not namespace-qualified, the schema without a target namespace having a root element same as the root element of the document becomes the primary schema.
If one of the above conditions are met, IDE will offer completion., when user types in the start tag "<" somewhere in the document, you'll see code completion. You can also invoke code completion at various level by pressing Ctrl and Space key togther.
XML Schema allows Wildcards. When using wildcards (xsd:any and xsd:anyAttribute) it is possible to constrain the content with the help of namespace. Both xsd:any and xsd:anyAttribute come with an optional namespace attribute that may contain any of the values shown in Namespace column in the Table below. This makes it possible to be very specific about where the wildcard replacement content comes from.
The IDE substitutes these wildcards as follows:
|If namespace is||Substitute with|
|##any||Any element from any namespace|
|##other||Any element from namespaces other than the targetNamespace|
|##targetNamespace||Any element from targetNamespace|
|##local||Any unqualified (no namespace)|
|List of URIs||Elements from the specified namespaces|
<a:RootA xmlns:a="http://xml.netbeans.org/schema/A" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml.netbeans.org/schema/A A.xsd http://xml.netbeans.org/schema/B B.xsd http://xml.netbeans.org/schema/C C.xsd"> < <= current cursor position </a:RootA>
In this example, RootA is one of the root elements defined in schema A.xsd. If RootA had a xsd:any child element, then at the cursor position you would see items appearing from various namespaces as per substitution rule above. Same applies for xsd:anyAttribute.
Insertion of Namespace Declaration
When user selects item from other namespaces (applicable only in cases of wildcard), the IDE will automatically insert a namespace declaration for that element it's not there. For example, if there was an xsd:any element, code completion would substitue the xsd:any with a list of valid elements. Some of these elements may come from other namespaces that may not have been declared in the document, in which case, the tool will automatically insert a namespace declaration.
The tool first tries a prefix "ns1" and if not found uses it. If found, it tries "ns2", "ns3" and so on. The declaration looks like this:
Where tns is target namespace for the selected element.