//
// Copyright (c) 2020 Contributors to the Eclipse Foundation
//

[appendix]
== External Binding Declaration

=== Example

*_Example:_* Consider the following schema and external binding file: +

Source Schema: `A.xsd`:

[source,xml]
----
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:ens="http://example.com/ns"
           targetNamespace="http://example.com/ns">
  <xs:complexType name="aType">
    <xs:sequence>
      <xs:element name="foo" type="xs:int"/>
    </xs:sequence>
    <xs:attribute name="bar" type="xs:int"/>
  </xs:complexType>
  <xs:element name="root" type="ens:aType"/>
</xs:schema>
----

External binding declarations file:

[source,xml]
----
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               version="3.0">
  <jaxb:bindings schemaLocation="A.xsd">
    <jaxb:bindings node="//xs:complexType[@name=’aType’]">
      <jaxb:class name="customNameType"/>
      <jaxb:bindings node=".//xs:element[@name=’foo’]">
        <jaxb:property name="customFoo"/>
      </jaxb:bindings>
      <jaxb:bindings node="./xs:attribute[@name=’bar’]">
        <jaxb:property name="customBar"/>
      </jaxb:bindings>
     </jaxb:bindings>
   </jaxb:bindings>
</jaxb:bindings>
----

Conceptually, the combination of the source
schema and external binding file above are the equivalent of the
following inline annotated schema.

[source,xml]
----
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:ens="http://example.com/ns"
           targetNamespace="http://example.com/ns"
           xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
           jaxb:version="3.0">
  <xs:complexType name="aType">
    <xs:annotation>
      <xs:appinfo>
        <jaxb:class name="customNameType"/>
      </xs:appinfo>
    </xs:annotation>
    <xs:sequence>
      <xs:element name="foo" type="xs:int">
        <xs:annotation>
          <xs:appinfo>
            <jaxb:property name="customFoo"/>
          </xs:appinfo>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="bar" type="xs:int">
      <xs:annotation>
        <xs:appinfo>
          <jaxb:property name="customBar"/>
        </xs:appinfo>
      </xs:annotation>
    </xs:attribute>
  </xs:complexType>
  <xs:element name="root" type="ens:aType"/>
</xs:schema>
----

=== Transformation

The intent of this section is to describe the
transformation of external binding declarations and their target schemas
into a set of schemas annotated with JAXB binding declarations. ready
for processing by a JAXB compliant schema compiler.

This transformation must be understood to
work on XML data model level. Thus, this transformation is applicable
even for those schemas which contain semantic errors.

The transformation is applied as follows:

. Gather all the top-most `<jaxb:bindings>`
elements from all the schema documents and all the external binding
files that participate in this process. _Top-most_ `<jaxb:bindings>` are
those `<jaxb:bindings>` elements that are either a root element in a
document or whose parent is an `<xs:appinfo>` element. We will refer to
these trees as “external binding forest.”
. Collect all the namespaces used in the
elements inside the external binding forest, except the taxi namespace,
`"https://jakarta.ee/xml/ns/jaxb"`, and the no namespace. Allocate an
unique prefix for each of them and declare the namespace binding at all
the root `<xs:schema>` elements of each schema documents. +
Then add a `jaxb:extensionBindingPrefix` attribute to each `<xs:schema>`
element with all those allocated prefixes. If an`<xs:schema>` element
already carries this attribute, prefixes are just appended to the
existing attributes. +
 +
Note: The net effect is that all “foreign” namespaces used in the
external binding forest will be automatically be considered as extension
customization declaration namespaces.
. For each `<jaxb:bindings>` element, we
determine the “target element” that the binding declaration should be
associated with. This process proceeds in a top-down fashion as follows:
+
--
.. Let `p` be the target element of the parent
`<jaxb:bindings>`. If it is the top most `<jaxb:bindings>`, then let
`p` be the `<jaxb:bindings>` element itself.
.. Identify the “target element” using `<jaxb:bindings>` attributes.
... If the `<jaxb:bindings>` has a `@schemaLocation`, the value of the
attribute should be taken as an URI and be absolutized with the base URI
of the `<jaxb:bindings>` element. Then the target element will be the
root node of the schema document identified by the absolutized URI. If
there’s no such schema document in the current input, it is an error.
Note: the root node of the schema document is not the document element.

... If the `<jaxb:bindings>` has `@node`,
the value of the attribute should be evaluated as an XPath 1.0
expression. The context node in this evaluation should be _p_ as we
computed in the previous step. It is an error if this evaluation results
in something other than a node set that contains exactly one element.
Then the target element will be this element.

... If the `<jaxb:bindings>` has neither
`@schemaLocation` nor `@node`, then the target element will be `p` as
we computed in the previous step. Note: `<jaxb:bindings>` elements can’t
have both `@schemaLocation` and `@node` at the same time.
--
+
We define the target element of a binding
declaration to be the target element of its parent `<jaxb:bindings>`
element. The only exception to this is `<jaxb:globalBindings>` binding
declaraiton, in which case the target element will be the document
element of any one of the schema documents being compiled (such choice
is undeterministic, but the semantics of `<jaxb:globalBindings>` is not
affected by this choice, so the end result will be the same.) It is an
error if a target element of a binding declaration doesn’t belong to the
_"http://wwww.w3.org/2001/XMLSchema"_ namespace.

. Next, for each target element of binding
declarations, if it doesn’t have any `<xs:annotation> <xs:appinfo>` in
its children, one will be created and added as the first child of the
target.
 +
After that, we move each binding declaration under the target node of
its parent `<jaxb:bindings>`. Consider the first `<xs:appinfo>` child
of the target element. The binding declaration element will be moved
under this `<xs:appinfo>` element.

