<?xml version="1.0" encoding="UTF-8"?>
<!--

    Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.

    This program and the accompanying materials are made available under the
    terms of the Eclipse Distribution License v. 1.0, which is available at
    http://www.eclipse.org/org/documents/edl-v10.php.

    SPDX-License-Identifier: BSD-3-Clause

-->

<!DOCTYPE book [
<!ENTITY % ents SYSTEM "docbook.ent">
%ents;
]>
<section version="5.0" xml:id="compiling-xml-schema-dealing-with-errors"
         xml:lang="en" xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:ns5="http://www.w3.org/1999/xhtml"
         xmlns:ns3="http://www.w3.org/2000/svg"
         xmlns:ns="http://docbook.org/ns/docbook"
         xmlns:m="http://www.w3.org/1998/Math/MathML">
    <title>Dealing with errors</title>

    <section xml:id="Schema_errors">
        <title>Schema errors</title>

        <para>Because XML Schema is so complicated, and because there are a
        lot of tools out there do not implement the spec correctly, it is
        often the case that a schema you are trying to compile has some real
        errors in it. When this is the case, you'll see XJC reporting somewhat
        cryptic errors such as <literal>rcase-RecurseLax.2: There is not a
        complete functional mapping between the particles.</literal></para>

        <para>The JAXB RI uses the schema correctness checker from the
        underlying JAXP implementation, which is the JAXP RI in a typical
        setup. The JAXP RI is one of the most conformant schema validators,
        and therefore most likely correct. So the first course of action
        usually is to fix problems in the schema.</para>

        <para>However, in some situations, you might not have an authority to
        make changes to the schema. If that is the case and you really need to
        compile the schema, you can bypass the correctness check by using the
        <option>-nv</option> option in XJC. When you do this, keep in mind
        that you are possibly feeding "garbage" in, so you may see XJC choke
        with some random exception.</para>
    </section>

    <section xml:id="Property__fooBarZot__is_already_defined">
        <title>Property 'fooBarZot' is already defined</title>

        <para>One of the typical errors you'll see when compiling a complex
        schema is:</para>

        <example>
            <title>Multiple property definitions error</title>

            <programlisting language="output"><![CDATA[parsing a schema...
[ERROR] Property "MiOrMoOrMn" is already defined.
  line 132 of
file:/C:/kohsuke/Sun/JAXB/jaxb-unit/schemas/individual/MathML2/presentation/scripts.xsd

[ERROR] The following location is relevant to the above error
  line 138 of
file:/C:/kohsuke/Sun/JAXB/jaxb-unit/schemas/individual/MathML2/presentation/scripts.xsd]]></programlisting>
        </example>

        <para>This is an actual example of the offending part of a schema,
        taken from MathML. If you go to line 132 of
        <filename>scripts.xsd</filename>, you'll see that it has a somewhat
        complicated content model definition:</para>

        <example>
            <title>Multiple property definitions in MathML</title>

            <programlisting language="xml"><![CDATA[<xs:group name="mmultiscripts.content">
    <xs:sequence>
        <xs:group ref="Presentation-expr.class"/>
        <xs:sequence minOccurs="0" maxOccurs="unbounded">      <!-- line 132 -->
            <xs:group ref="Presentation-expr-or-none.class"/>
            <xs:group ref="Presentation-expr-or-none.class"/>
        </xs:sequence>
        <xs:sequence minOccurs="0">
            <xs:element ref="mprescripts"/>
            <xs:sequence maxOccurs="unbounded">                 <!-- line 138 -->
                <xs:group ref="Presentation-expr-or-none.class"/>
                <xs:group ref="Presentation-expr-or-none.class"/>
            </xs:sequence>
        </xs:sequence>
    </xs:sequence>
</xs:group>]]></programlisting>
        </example>

        <para>This is a standard technique in designing a schema. When you
        want to say "in this element, <literal>B</literal> can occur arbitrary
        times, but <literal>C</literal> can occur only up to once", you write
        this as <literal>B*,(C,B*)?</literal>. This, however, confuses JAXB,
        because it tries to bind the first <literal>B</literal> to its own
        property, then <literal>C</literal> to its own property, then the
        second <literal>B</literal> to its own property, and so we end up
        having a collision again.</para>

        <para>In this particular case, <literal>B</literal> isn't a single
        element but it's a choice of large number of elements abstracted away
        in <literal>&lt;xs:group&gt;</literal>s, so they are hard to see. But
        if you see the same content model referring to the same element/group
        twice in a different place, you can suspect this.</para>

        <para>In this case, you'd probably want the whole thing to map to a
        single list so that you can retain the order those elements show up in
        the document. You can do this by putting the same
        <literal>&lt;jaxb:property&gt;</literal> customization on the whole
        "<literal>mmultiscripts.content</literal>" model group, like this (or
        you can do it externally with XPath):</para>

        <example>
            <title>How to fix the problem?</title>

            <programlisting language="xml"><![CDATA[<xs:groupname="mmultiscripts.content">
<xs:annotation>
    <xs:appinfo>
        <jaxb:propertyname="content"/>
    </xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:groupref="Presentation-expr.class"/>]]></programlisting>
        </example>

        <para>Another way to fix this problem is to use the
        simpler and better binding mode in XJC, which is a JAXB RI
        vendor extension.</para>
    </section>

    <section xml:id="Two_declarations_cause_a_collision_in_the_ObjectFactory_class">
        <title>Two declarations cause a collision in the ObjectFactory
        class</title>

        <para>When schemas contain similar looking element/type names, they
        can result in "Two declarations cause a collision in the ObjectFactory
        class" errors. To be more precise, for each of all types and many
        elements (exactly what elements get a factory and what doesn't is bit
        tricky to explain), XJC produces one method on the
        <literal>ObjectFactory</literal> class in the same package. The
        <literal>ObjectFactory</literal> class is created for each package that XJC
        generates some files into. The name of the method is derived from XML
        element/type names, and the error is reported if two elements/types
        try to generate the same method name.</para>

        <para>There are two approaches to fix this problem. If the collision
        is coming from two different schemas with different target namespaces,
        then you can easily avoid the collision by compiling them into
        different Java packages. To do this, use <literal>&lt;schemabindings&gt;</literal>
        customization on two schemas and specify the package name.</para>

        <para>Another way to fix this problem is to use <literal>&lt;factoryMethod&gt;</literal>
        customization on two conflicting elements/types to specify different
        factory method names. This can be used in all cases, but if you have a
        large number of conflicts, you'll have to specify this customization
        one by one.</para>

        <para>Notice that <literal>&lt;class&gt;</literal>
        customization doesn't affect the <literal>ObjectFactory</literal> method
        name by itself.</para>
    </section>

    <section xml:id="Customization_errors">
        <title>Customization errors</title>

        <section xml:id="XPath_evaluation_of_____results_in_empty_target_node">
            <title>XPath evaluation of ... results in empty target
            node</title>

            <para>External JAXB customizations are specified by using XPath
            (or using <link
            xlink:href="customization-of-schema-compilation-using-scd-for-customizations">SCD</link>.)
            This works by writing an XPath expression that matches a
            particular element in the schema document. For example, given the
            following schema and binding file:</para>

            <example>
                <title>Schema and external binding file</title>

                <formalpara>
                    <title><filename>test.xsd</filename></title>

                    <para><programlisting language="xml"><![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexTypename="foo"/>
</xs:schema>]]></programlisting></para>
                </formalpara>

                <formalpara>
                    <title><filename>test.xjb</filename></title>

                    <para><programlisting language="xml"><![CDATA[<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <bindings schemaLocation="test.xsd">
        <bindings node="//xs:complexType[@name='foo']">
            <classname="Bar"/>
        </bindings>
    </bindings>
</bindings>]]></programlisting></para>
                </formalpara>
            </example>

            <para>will be interpreted as if the class customization is
            attached to the complex type '<literal>foo</literal>'.</para>

            <para>For this to work, the XPath expression needs to match one
            and only one element in the schema document. When the XPath
            expression is incorrect and it didn't match anything, you get this
            "XPath evaluation of ... results in empty target node"
            problem.</para>

            <para>Common causes of this problem include typos, incorrect
            namespace URI declarations, and misunderstanding of XPath.</para>
        </section>
    </section>
</section>
