Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 190 additions & 54 deletions docs/BindingWithGrammar.md
Original file line number Diff line number Diff line change
@@ -1,119 +1,255 @@
# Binding with Grammar

[vscode-xml](https://github.com/redhat-developer/vscode-xml) provides support for automatic XML schema/grammar binding through generation and/or using an existing `.xsd/.dtd` file.
[vscode-xml](https://github.com/redhat-developer/vscode-xml) provides support for automatic XML schema/grammar binding through generation and/or using an existing `.xsd/.dtd/.rng/.rnc` file.

> **Tip:** You can also [generate a grammar from an XML document](GenerateGrammarFromXML.md) or [generate an XML document from a grammar](GenerateXMLFromGrammar.md).

![Binding Wizard Demo](./images/BindingWithGrammar/BindingWizardDemo.gif)

[Validation with XSD grammar](Validation.md#validation-with-xsd-grammar) and [Validation with DTD grammar](Validation.md#validation-with-dtd-grammar) provide more information on manual binding of an XML document.

In the following sections, we would like to bind the XML document `foo.xml`:
```xml
<foo>
<bar />
</foo>
```
with an associated grammar file.
The binding wizard can be triggered by [Command](#command), [CodeLens](#codelens), or [Quick Fix](#quick-fix).

In the following sections, we would like to bind the XML document `team.xml` with a grammar file.

## Binding with Existing Grammar
Consider an XSD document, `team.xsd` (in the same directory as `team.xml`), that declares **two root elements** (`person` and `team`):

Consider an XSD document, `foo.xsd` (in the same directory as `foo.xml`), defined as follows :
```xsd
```xml
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="foo">
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element name="age" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="team">
<xs:complexType>
<xs:sequence>
<xs:element name="bar" />
<xs:element name="name" type="xs:string" />
<xs:element ref="person" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
```
and a DTD document, `foo.dtd` (in the same directory as `foo.xml`), defined as follows:

a DTD document, `team.dtd` (in the same directory as `team.xml`):

```dtd
<!ELEMENT foo (bar)>
<!ELEMENT bar EMPTY>
<!ELEMENT person (name, age)>
<!ELEMENT team (name, person+)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
```

Either file can be bound using the [XML Binding Wizard](#the-xml-binding-wizard), which can be triggered by [Command](#command), [CodeLens](#codelens) or [Quick Fix](#quick-fix).
and a RelaxNG document, `team.rng` (in the same directory as `team.xml`):

### The XML Binding Wizard
```xml
<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
<choice>
<ref name="person"/>
<ref name="team"/>
</choice>
</start>
<define name="person">
<element name="person">
<element name="name"><text/></element>
<element name="age"><text/></element>
</element>
</define>
<define name="team">
<element name="team">
<element name="name"><text/></element>
<oneOrMore>
<ref name="person"/>
</oneOrMore>
</element>
</define>
</grammar>
```

After opening the binding wizard using one of the methods mentioned above, a dropdown with the following 2 options will appear at the Command Palette:
or equivalently in RelaxNG Compact syntax, `team.rnc`:

```rnc
start = person | team

person = element person {
element name { text },
element age { text }
}

team = element team {
element name { text },
person+
}
```

After opening the binding wizard, a dropdown with 3 options appears at the Command Palette:

![Binding Wizard Dropdown](./images/BindingWithGrammar/BindingWizardDropdown.png)

1. Standard (xsi, DOCTYPE)
For Standard and XML Model options, a file explorer lets you select the grammar file:

![Binding Wizard File Explorer](./images/BindingWithGrammar/BindingWizardFileExplorer.png)

## Standard (xsi, DOCTYPE)

### XSD binding

If the selected file is an XSD file, this option binds the grammar by adding the `xmlns:xsi` (with the value `http://www.w3.org/2001/XMLSchema-instance`) and `xsi:noNamespaceSchemaLocation` (with the path to the grammar file) attributes to the root tag.

Since `team.xsd` declares **two root elements** (`person` and `team`), vscode-xml uses a **SnippetTextEdit** with a [choice placeholder](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#snippet_syntax), letting you pick the root element directly in the editor:

![Snippet Choice XSI](./images/BindingWithGrammar/SnippetChoiceXSI.png)

After selecting `person`:
```xml
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="team.xsd"></person>
```

> **Note:** If the XSD declares a single root element, a regular TextEdit is used directly without the choice dropdown.

### With targetNamespace

If the XSD declares a `targetNamespace` with `elementFormDefault="qualified"`:
```xml
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.org/team"
elementFormDefault="qualified">
```
then the binding uses `xmlns` and `xsi:schemaLocation` instead:
```xml
<person xmlns="http://example.org/team"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.org/team team-ns.xsd"></person>
```

### DTD binding

If the selected file is a DTD file, this option adds a `<!DOCTYPE>` declaration at the beginning of the document:

![Snippet Choice DOCTYPE](./images/BindingWithGrammar/SnippetChoiceDOCTYPE.png)

After selecting `team`:
```xml
<!DOCTYPE team SYSTEM "team.dtd">
<team></team>
```

## XML Model association

This option binds the grammar by adding an `<?xml-model?>` processing instruction at the beginning of the document:

If the selected file is an XSD file, this option will bind the grammar file by adding the `xmlns:xsi` (with the value as "http://www.w3.org/2001/XMLSchema-instance") and `xsi:noNamespaceSchemaLocation` (with the value as the path to the grammar file) attributes to the root tag:
![Snippet Choice XML Model](./images/BindingWithGrammar/SnippetChoiceXMLModel.png)

After selecting `person` with an XSD file:
```xml
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="foo.xsd">
<bar />
</foo>
<?xml-model href="team.xsd"?>
<person></person>
```

If the XSD file contains a `targetNamespace` attribute, with an `elementFormDefault` attribute with value "qualified" in the `xs:schema` tag, as follows:
```xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://foo" elementFormDefault="qualified">
The same applies when selecting a DTD file:
```xml
<?xml-model href="team.dtd"?>
<team></team>
```
then the XML document will have the `targetNamespace` set as a `xmlns` attribute and an additional attribute for `xsi:schemaLocation`:

### RelaxNG binding

When selecting a RelaxNG file (`.rng` or `.rnc`), the `<?xml-model?>` processing instruction:

For a `.rng` (XML syntax) file:
```xml
<foo xmlns="http://foo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://foo foo.xsd">
<bar />
</foo>
<?xml-model href="team.rng"?>
<team></team>
```

If the selected file is a DTD file, this option will bind the grammar file by adding a `<!DOCTYPE <root-tag-name> SYSTEM "<grammar-file-path>">` tag at the beginning of the document:
For a `.rnc` (Compact syntax) file:
```xml
<!DOCTYPE foo SYSTEM "foo.dtd">
<foo>
<bar />
</foo>
<?xml-model href="team.rnc"?>
<team></team>
```

2. XML Model association
> **Note:** RelaxNG grammars can only be bound via XML Model or Catalog entry, not via Standard (xsi, DOCTYPE).

## Catalog entry

This option binds the XML document through an [XML Catalog](https://www.oasis-open.org/committees/entity/spec-2001-08-06.html). An XML Catalog is a mapping file that redirects XML identifiers (public IDs, system IDs, URIs) to local grammar resources, allowing you to manage grammar bindings centrally rather than embedding paths in each XML file.

When you select this option, the wizard presents two choices:

### Pick an existing catalog entry

This option will bind the grammar file by adding the `xml-model` tag at the beginning of the document, with an `href` value as the path to the grammar file:
If your workspace has registered catalogs (via the `xml.catalogs` setting) that already contain entries, they are listed grouped by catalog file. Selecting an entry inserts the appropriate binding in your XML document (DOCTYPE for public/system entries, xsi:schemaLocation for XSD entries).

![Catalog Entries List](./images/BindingWithGrammar/BindingWizardCatalogEntries.png)

With multiple root elements, the choice placeholder lets you select the root element, just like with Standard and XML Model options.

### Add a new catalog entry

If no existing entry matches, select "Add new catalog entry..." at the bottom of the list.

![Catalog Add New Entry](./images/BindingWithGrammar/BindingWizardCatalogAddNewEntry.png)

The wizard will:

1. Ask which catalog should contain the new entry (an existing registered catalog, browse for another catalog file, or create a new catalog file)

![Catalog Selection](./images/BindingWithGrammar/BindingWizardCatalogSelect.png)

2. Ask for the entry type (`public`, `system`, or `uri`)
3. Ask for the identifier (the public ID, system ID, or namespace URI)
4. Let you select the grammar file

The entry is added to the catalog file, the catalog is registered in `xml.catalogs` if needed, and the XML document is bound using the catalog entry.

For example, with a `public` catalog entry, the resulting binding is a PUBLIC DOCTYPE:
```xml
<!DOCTYPE team PUBLIC "-//Example//DTD Team//EN" "team.dtd">
<team></team>
```

With a `uri` catalog entry pointing to an XSD with a target namespace, the result uses `xsi:schemaLocation`:
```xml
<?xml-model href="foo.xsd"?>
<foo>
<bar />
</foo>
<person xmlns="http://example.org/team"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.org/team team-ns.xsd"></person>
```
The same applies when selecting `foo.dtd`.

After selecting an option, you can select the desired grammar file using your file explorer:
> **Note:** The generated catalog entry respects your formatting settings (indentation, tab/spaces, space before empty close tag).

![Binding Wizard File Explorer](./images/BindingWithGrammar/BindingWizardFileExplorer.png)
## Triggers

The binding wizard can be triggered in three ways:

### Command

The command "XML: Bind to grammar/schema file" can be executed from the VSCode command palette, as well as be bound to a shortcut.

![Bind To Grammar Command](./images/BindingWithGrammar/BindToGrammarCommand.png)

If the current XML document is not bound using an existing grammar/schema, the command will have the user select a existing `.xsd/.dtd` grammar file to bind to the XML document.

Otherwise, an error will be thrown on the client if the XML document already has a bound grammar/schema.
If the current XML document already has a bound grammar/schema, an error will be shown.

### CodeLens

When [CodeLenses](./Preferences.md#code-lens) are enabled, an unbound XML document will display a CodeLens above the root element as follows:
When [CodeLenses](./Preferences.md#code-lens) are enabled, an unbound XML document will display a CodeLens above the root element:

![Bind To Grammar Command](./images/BindingWithGrammar/BindToGrammarCodeLens.png)
![Bind To Grammar CodeLens](./images/BindingWithGrammar/BindToGrammarCodeLens.png)

### Quick Fix

For any unbound XML document, a Quick Fix suggestion will appear beside the root element.

![Bind To Grammar CodeAction](./images/BindingWithGrammar/BindToGrammarCodeAction.png)

With the cursor on the first opening tag, use `Ctrl + .`, `Quick Fix...` or the lightbulb that appears and select the "Bind to existing grammar/schema"
With the cursor on the first opening tag, use `Ctrl + .`, `Quick Fix...` or the lightbulb that appears and select "Bind to existing grammar/schema":

![Bind To Grammar CodeAction Dropdown](./images/BindingWithGrammar/BindToGrammarCodeActionDropdown.png)

Expand Down
4 changes: 4 additions & 0 deletions docs/Features/DTDFeatures.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# DTD Features

## Binding

See [Binding with Grammar](../BindingWithGrammar.md#dtd-binding) to associate an XML file with a DTD using the binding wizard.

## CodeLens Support

CodeLens is supported for `.dtd` files, which can show where an element declaration is referenced.
Expand Down
3 changes: 2 additions & 1 deletion docs/Features/RelaxNGFeatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ It supports both:

You can associate your XML file with `RelaxNG grammar` (`file` or `URL`) using :

* the [Binding Wizard](../BindingWithGrammar.md#relaxng-binding) (XML Model or Catalog entry)
* an `xml-model` processing instruction

```xml
Expand Down Expand Up @@ -147,4 +148,4 @@ The following file, `addressBook.xml`, references `addressBook.rng` using the `x

When an unbound XML file is open, a RELAX NG schema can be generated from the opening tag in the XML file.

See: [Generate RELAX NG from XML](../BindingWithGrammar.md#generate-relax-ng-from-xml).
See: [Generate Grammar from XML](../GenerateGrammarFromXML.md).
4 changes: 4 additions & 0 deletions docs/Features/XMLCatalogFeatures.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# XML Catalog Features

## Binding with Catalog

The [Binding Wizard](../BindingWithGrammar.md#catalog-entry) supports binding an XML document to a grammar through an XML Catalog entry. You can pick an existing catalog entry or add a new one directly from the wizard.

## Validation

XML Catalog is supported with both DTD and XSD. Please see here for more information on the usage of [XML Catalog With DTD](../Validation.md#xml-catalog-with-dtd) and [XML Catalog With XSD](../Validation.md#xml-catalog-with-xsd).
Expand Down
4 changes: 4 additions & 0 deletions docs/Features/XSDFeatures.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# XSD Features

## Binding

See [Binding with Grammar](../BindingWithGrammar.md#xsd-binding) to associate an XML file with an XSD using the binding wizard.

## CodeLens Support

CodeLens is supported for `.xsd` files, which can show where a type is referenced.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/BindingWithGrammar/BindingWizardDemo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/BindingWithGrammar/BindingWizardDropdown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/BindingWithGrammar/BindingWizardFileExplorer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading