XSD konfigurieren mit eigenen Typen

lam_tr

Top Contributor
Hallo zusammen,

ich habe folgendes Schema
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.0">

    <xs:annotation>
        <xs:appinfo>
            <jaxb:globalBindings>
                <xjc:serializable uid="1" />
            </jaxb:globalBindings>
        </xs:appinfo>
    </xs:annotation>

  <xs:element  name="CONTENT" type="Content"/>
 
   <xs:complexType name="Content">
    <xs:sequence>
      <xs:element minOccurs="0" name="INFO" type="Info"/>
      <xs:element minOccurs="0" name="DESCR" type="Description"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Info"/>
  <xs:complexType name="Description"/>
</xs:schema>

wie kann ich das Schema mit xmlns so definieren, dass in meiner XML Datei diesen Namensraum habe? Es scheint nicht gültig zu sein weil ich den Default NS überschreiben möchte.

Code:
<?xml version="1.0" encoding="UTF-8"?>
<CONTENT xmlns="http://example.com/content">
  <INFO/>
  <DESCR/>
</CONTENT>

Hier noch die Fehlermeldung, wenn ich den Namensraum direkt in das XSD hinzufüge
Code:
src-resolve.4.2: Error resolving component 'Content'. It was detected that 'Content' is in
 namespace 'http://example.com/content', but components from this namespace are not
 referenceable from schema document...


Hat da jemand eine Idee für mich? Ich weiß zwar was ein NS ist, aber das mit der Definition in XSD hänge ich gerade.

Viele Grüße
lam
 
Zuletzt bearbeitet:
K

kneitzel

Gast
Im xsd solltest Du targetNamespace definieren. Wenn es http://example.com/content sein soll, dann solltest Du das so schreiben:
Code:
<xs:schema ..... targetNamespace="http://example.com/content" ....>

Und wie nutzt Du es? Gibst Du das xsd bereits mit an, so dass es bekannt ist? Wenn es automatisch geladen werden soll, dann könntest Du im xml noch angeben: xsi:schemaLocation="<URL der XSD Datei>" also z.b. sowas wie xsi:schemaLocation="https://my.cool.comain/myXsdFile.xsd"
 

lam_tr

Top Contributor
Im xsd solltest Du targetNamespace definieren. Wenn es http://example.com/content sein soll, dann solltest Du das so schreiben:
Code:
<xs:schema ..... targetNamespace="http://example.com/content" ....>

Und wie nutzt Du es? Gibst Du das xsd bereits mit an, so dass es bekannt ist? Wenn es automatisch geladen werden soll, dann könntest Du im xml noch angeben: xsi:schemaLocation="<URL der XSD Datei>" also z.b. sowas wie xsi:schemaLocation="https://my.cool.comain/myXsdFile.xsd"

Vielen Dank für die schnelle Antwort.

Wenn ich der XML die XSD nicht mitbegebe, dann funktioniert das mit dem TargetNamespace nicht.

Ich habe stattdessen im xs:schema xmlns:ct="http://www.example.com/content" erweitert.

Bin mir nicht sicher ob das der richtige Weg ist, auf jeden Fall validiert die XML jetzt.

Was meinst du dazu?
 
K

kneitzel

Gast
Also in der xsd gibst Du im xs tag an:
- xmlns[:Kürzel]="..." Namespaces, die Du selbst nutzen willst. (Hast Du ja mehrere, xs, xjc, ...
- targetNamespace="..." Welchen Namespace beschreibst Du denn in dem xsd File?

Daher würde ich das xsd so erweitern:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.0"
targetNamespace="http://example.com/content">

Das mal ohne code-Tags damit das zusätzliche sichtbar ist, das ich einfügen würde.

Denn so erkennt das System nun, dass das xsd eben http://example.com/content definiert. (Da solltest Du aber nicht example.com verwenden, aber das war evtl. ja nur ein Beispiel...)

Das XML sollte dann so ok sein. Also einfach mit dem ersten Element so anfangen und daden default Namespace setzen. Du kannst natürlich auch ein benannten Namespace nehmen indem du da xmlns:ct="..." statt xmlns="..." nutzt, aber dann musst Du natürlich den Elementen den Namespace ct: voran stellen. Aber das xml sollte so ok sein, wie du es in #1 angegeben hast.

Wenn Du dem Parser im Code nicht das xsd schon mitgibst, dann müsste er wissen, wo er das xsd File findet. Das ist, was ich noch kurz mit schemaLocation angesprochen habe. Das wäre dann etwas wie:

Code:
<?xml version="1.0"?>
<CONTENT xmlns="http://example.com/content"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://valid url/to/xsd_file.xsd">
 

lam_tr

Top Contributor
Vielen Dank für die detaillierte Erklärung. Die XSD wird bei XML nicht mitgegeben.

Die Validierung geschieht in dieser Form programmatisch.

Code:
public static void main(String[] args) {
        XMLValidator XMLValidator = new XMLValidator();
        boolean valid = XMLValidator.validate(XML_FILE, SCHEMA_FILE);

        System.out.printf("%s validation = %b.", XML_FILE, valid);
    }

    private boolean validate(String xmlFile, String schemaFile) {
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        try {
            Schema schema = schemaFactory.newSchema(new File(SCHEMA_FILE));

            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(XML_FILE)));
            return true;
        } catch (SAXException | IOException e) {
            e.printStackTrace();
            return false;
        }
    }

Grüße
lam
 
K

kneitzel

Gast
Ja, das meinte ich. Du lädst das Schema bereits im Programm. Damit brauchst Du das xsi:schemaLocation und den xsi Namespace nicht im XML.

Und dank Deines Codes habe ich das jetzt auch noch einmal schnell getestet. Was ich natürlich übersehen habe:
Du definierst keinen default Namespace. Du definierst einen Typ "Context" und der hat damit kein Namespace. Setz noch den default namespace in der xsd Datei:

Code:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.0"
    targetNamespace="http://example.com/content" xmlns="http://example.com/content">

Damit funktioniert es dann auch mit Deinem Code.

Zur Vollständigkeit einfach einmal, was ich erfolgreich getestet habe:

test.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<CONTENT xmlns="http://example.com/content">
  <INFO/>
  <DESCR/>
</CONTENT>

test.xsd
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.0"
    targetNamespace="http://example.com/content" xmlns="http://example.com/content">

    <xs:annotation>
        <xs:appinfo>
            <jaxb:globalBindings>
                <xjc:serializable uid="1" />
            </jaxb:globalBindings>
        </xs:appinfo>
    </xs:annotation>

  <xs:element  name="CONTENT" type="Content"/>
 
   <xs:complexType name="Content">
    <xs:sequence>
      <xs:element minOccurs="0" name="INFO" type="Info"/>
      <xs:element minOccurs="0" name="DESCR" type="Description"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Info"/>
  <xs:complexType name="Description"/>
 
</xs:schema>

XMLValidator.java
Code:
import org.xml.sax.SAXException;

import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.IOException;

public class XMLValidator {
    public static String XML_FILE = "./test.xml";
    public static String SCHEMA_FILE = "./test.xsd";

    public static void main(String[] args) {
        XMLValidator XMLValidator = new XMLValidator();
        boolean valid = XMLValidator.validate(XML_FILE, SCHEMA_FILE);

        System.out.printf("%s validation = %b.", XML_FILE, valid);
    }

    private boolean validate(String xmlFile, String schemaFile) {
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        try {
            Schema schema = schemaFactory.newSchema(new File(SCHEMA_FILE));

            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(XML_FILE)));
            return true;
        } catch (SAXException | IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}
 

Ähnliche Java Themen

Neue Themen


Oben