Tagged: xml schema

Serving XML Schema with JAX-RS


update

@GET
@Path("/some.xsd")
@Produces({MediaType.APPLICATION_XML})
public Response readSomeXsd() throws JAXBException, IOException {

    final JAXBContext context; // get some

    return Response.ok((StreamingOutput) output -> {
        context.generateSchema(new SchemaOutputResolver() {
            @Override
            public Result createOutput(final String namespaceUri,
                                       final String suggestedFileName)
                throws IOException {
                final Result result = new StreamResult(output);
                result.setSystemId(uriInfo.getAbsolutePath().toString());
                return result;
            }
        });
    }).build();
}

@Context
private transient UriInfo uriInfo;

You can serve the XML Schema for your domain objects.

public class SchemaStreamingOutput implements StreamingOutput {

    public SchemaStreamingOutput(final JAXBContext context) {
        super();

        if (context == null) {
            throw new NullPointerException("null context");
        }

        this.context = context;
    }

    @Override
    public void write(final OutputStream output) throws IOException {

        context.generateSchema(new SchemaOutputResolver() {

            @Override
            public Result createOutput(final String namespaceUri,
                                       final String suggestedFileName)
                throws IOException {

                return new StreamResult(output) {

                    @Override
                    public String getSystemId() { // nasty
                        return suggestedFileName;
                    }
                };
            }
        });
    }

    private final JAXBContext context;
}

Now you can serve your XML Schema like this.

@GET
@Path("/items.xsd")
@Produces({MediaType.APPLICATION_XML})
public Response readXsd() throws JAXBException {

    final JAXBContext context = ...;

    return Response.ok(new SchemaStreamingOutput(context)).build();
}

XML Schema strings with JAXB


References

package com.googlecode.jinahya.test;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;

/**
 *
 * @author Jin Kwon <jinahya at gmail.com>
 */
@XmlRootElement(name = "bind")
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder = {"token", "norma", "strin"})
public class StringBind {

    public static void main(final String[] args)
        throws JAXBException, IOException {

        final JAXBContext context = JAXBContext.newInstance(StringBind.class);

        // XML Schema ----------------------------------------------------------
        final StringWriter schemaWriter = new StringWriter();
        context.generateSchema(new SchemaOutputResolver() {
            @Override
            public Result createOutput(final String namespaceUri,
                                       final String suggestedFileName)
                throws IOException {
                return new StreamResult(schemaWriter) {
                    @Override
                    public String getSystemId() {
                        return suggestedFileName;
                    }
                };
            }
        });
        schemaWriter.flush();
        System.out.println("-------------------------------------- XML Schema");
        System.out.println(schemaWriter.toString());

        final String unprocessed = "\t ab\r\n   c\t \r \n";

        // marshal -------------------------------------------------------------
        final StringBind marshalling = new StringBind();
        marshalling.token = unprocessed;
        marshalling.norma = unprocessed;
        marshalling.strin = unprocessed;
        final Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        final StringWriter writer = new StringWriter();
        marshaller.marshal(marshalling, writer);
        writer.flush();
        System.out.println("-------------------------------------- marshalled");
        System.out.println(writer.toString());

        // unmarshal -----------------------------------------------------------
        final Unmarshaller unmarshaller = context.createUnmarshaller();
        final StringBind unmarshalled = (StringBind) unmarshaller.unmarshal(
            new StringReader(writer.toString()));
        System.out.println("------------------------------------ unmarshalled");
        System.out.println(unmarshalled.toString());
    }

    @Override
    public String toString() {
        return "token: " + token + "\nnorma: " + norma + "\nstrin: " + strin;
    }

    @XmlElement
    @XmlSchemaType(name = "token")
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    private String token;

    @XmlElement
    @XmlSchemaType(name = "normalizedString")
    @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
    private String norma;

    @XmlElement
    //@XmlSchemaType(name = "string") // @@?
    //@XmlJavaTypeAdapter(StringAdapter.class) // there is no StringAdapter.class
    private String strin;
}

Note that NormalizedStringAdapter#marshal(String) and CollapsedStringAdapter#marshal(String) don’t do anything.

-------------------------------------- XML Schema
<?xml version="1.0" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="bind" type="stringBind"/>

  <xs:complexType name="stringBind">
    <xs:sequence>
      <xs:element name="token" type="xs:token" minOccurs="0"/>
      <xs:element name="norma" type="xs:normalizedString" minOccurs="0"/>
      <xs:element name="strin" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>


-------------------------------------- marshalled
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bind>
    <token>	 ab
   c	  
</token>
    <norma>	 ab
   c	  
</norma>
    <strin>	 ab
   c	  
</strin>
</bind>

------------------------------------ unmarshalled
token: ab c
norma:   ab    c    
strin: 	 ab
   c	  

import XML namespace in your XML Schema


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:xml="http://www.w3.org/XML/1998/namespace" ...>
  <!--
  <xs:import namespace="http://www.w3.org/XML/1998/namespace"
             schemaLocation="http://www.w3.org/XML/1998/xml.xsd"/>
  -->
  <xs:import namespace="http://www.w3.org/XML/1998/namespace"
             schemaLocation="http://www.w3.org/2001/03/xml.xsd"/>
  ...
</xs:schema>