poprawny xsd na podstwie xml

0

hej, jak na podstawie xml'a moge stworzyc xsd? tzn wpierw stworzylam sobie wzorcowego xml'a, teraz chce napisac xsd a potem walidowac nowe xmle.

Przykladowy, wzorcowy xml:

 <?xml version="1.0"?>
<Person>
<name>Jan</name>
<surname>Kowalski</surname>
</Person>

xsd:

 <?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/test" xmlns:tns="http://www.example.org/test" elementFormDefault="qualified">
	<xs:element name="Person">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="name" type="xs:string" />
				<xs:element name="surname" type="xs:string" />
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>

ale to mi rzuca SaxException:
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'Person'.

on tam chyba by chcial typ dla Person? Ale Person nie ma zadnego typu, to tylko tag. Kopie i kopie, znalazlam nawet jakis generator xsd ale tez mi sie kaszani. Moze komus z Was rzucilo sie w oczy co tu jest nie tak?

pzdr,
misty

0

on tam chyba by chcial typ dla Person? Ale Person nie ma zadnego typu, to tylko tag. Kopie i kopie, znalazlam nawet jakis generator xsd ale tez mi sie kaszani. Moze komus z Was rzucilo sie w oczy co tu jest nie tak?

Person ma typ, tyle że anonimowy. Generacja XML z XSD jest w Eclipse. W drugą stronę nie wiem, nie używałem. W oczy rzuca się to, że w schemacie masz określone targetNamespace, a XML jest poza przestrzenią nazw. Wyjścia są dwa: zdefiniować XSD dla dokumentu bez określonej przestrzeni nazw, albo określić dla tagu Person atrybut xmlns.

 
<?xml version="1.0"?>
<Person xmlns="http://www.example.org/test">
<name>Jan</name>
<surname>Kowalski</surname>
</Person>
0

, a XML jest poza przestrzenią nazw. Wyjścia są dwa: zdefiniować XSD dla dokumentu bez określonej przestrzeni nazw, albo określić dla tagu Person atrybut xmlns.

XML jest poza przestrzenia nazw - nie rozuimem co masz na mysli?

zdefiniować XSD dla dokumentu bez określonej przestrzeni nazw - tego tez nie kumam

dla tagu Person atrybut xmlns - ale wtedy chyba nie bede mogla uzywac name, type dla pozostalych..

ps.
wlasnie generatorow w druga strone za bardzo nie ma.. nie wiem za bardzo jak napisac sobie to sama? Przyklady sa, owszem, robie wg nich a tu w sumie bledy z kosmosu przy tak banalnym przykladzie.. :/

pzdr

1

XML jest poza przestrzenia nazw - nie rozuimem co masz na mysli?

Konkretnie to nie XML, ale element ma przestrzeń nazw. Przykładowo każdy może sobie nazwać swój tag

http://www.w3.org/1999/xhtml (i nie jest to żaden adres). Resztę co i jak to można sobie doczytać.
W twoim konkretnym przypadku możesz napisać taki XSD:</p>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/test" elementFormDefault="qualified">
	<xs:element name="Person">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="name" type="xs:string" />
				<xs:element name="surname" type="xs:string" />
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>
 

Atrybut targetNamespace określa w jakiej przestrzeni nazw będzie element root dokumentu zgodnego z tym schematem. Przykładowy XML będzie taki:

 <?xml version="1.0" encoding="UTF-8"?>
<Person xmlns="http://www.example.org/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.example.org/test namespace.xsd ">
	<name>name</name>
	<surname>surname</surname>
</Person>

lub taki:

 <?xml version="1.0" encoding="UTF-8"?>
<tns:Person xmlns:tns="http://www.example.org/test"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.example.org/test namespace.xsd ">
	<tns:name>name</tns:name>
	<tns:surname>surname</tns:surname>
</tns:Person>

W obu zdefiniowana jest przestrzeń nazw "http://www.example.org/test" przy czym w pierwszym jest domyślna, a w drugim powiązana z prefikem tns (to skrót od targetNamespace i może być dowolny).
Schemat dla dokumentu bez określonej przestrzeni nazw nie ma tego atrybutu:

 
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:element name="Person">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="name" type="xs:string" />
				<xs:element name="surname" type="xs:string" />
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>

Ponieważ XSD też jest XMLem można zauważyć, że tagi należące do XSD, tutaj oznaczone prefiksem xs należą do przestrzeni nazw "http://www.w3.org/2001/XMLSchema". Dzięki temu możesz w swoim XML zdefiniować element o nazwie element i parser będzie wiedział, że to twój element, a nie ten z XSD. Ale tu jest akurat Person.

 <?xml version="1.0" encoding="UTF-8"?>
<Person>
	<name>name</name>
	<surname>surname</surname>
</Person>

Tutaj usunąłem atrybuty dotyczące powiązania ze schematem, żeby było jeszcze jaśniej ( xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="nonamespace.xsd").

Przestrzenie nazw są niezbędne, jeżeli w jednym XML znajduje się inny, np. osadzanie svg w xhtml, osadzanie schematu XSD w plikach WSDL, rozszerzenia ws-security w kopertach SOAP i jeszcze wiele innych. XML bez określonej przestrzeni nazw jest prostszy w obsłudze i w wielu zastosowaniach będzie wystarczający.

0

Dzieki za obszerna odpowiedz! Chociaz przyznam szczerze ze 3 razy czytalam :) Ale spoko, juz kumam wiecej niz mniej. Przyklad tez mi dziala, wiec jestem juz w stanie napisac sobie bardziej zlozonego xsd.
Ale mam jeszcze jedno pytanie. Wiem ze mozna sobie dla pol definiowac typy, np:

 
 <xs:element name="surname" type="xs:int" />
lub
 <xs:element name="surname" type="xs:string" />

Z tego jednak co widze i testuje, to majac definicje: **<xs:element name="surname" type="xs:string" /> ** moge sobie do surname podstawic co chce i bedzie ok, np: <surname>8</surname> i to bedzie dla validatora ok. Z kolei jesli bym w xsd miala surname typ jako int, zas w xmlu bym ustawila surname na np
<surname>Kowalski</surname> to pojdzie blad (czyli tak jak sie spodziewam). Mam rozumiec zatem ze dla Stringa ta walidacja nie do konca dziala? tzn. oczywiscie, String moze zawierac cyfry, ale jesli zawiera tylko cyfry to czy nie powinien byc traktowany jako int? A moze inaczej sie to ustawia?

pzdr,
misty

0

Możesz stworzyć swój własny typ tak aby wykluczyć ze Stringu cyfry za pomocą wzorców.

http://www.w3schools.com/schema/schema_facets.asp

0

No może zawile to napisałem, ale pewnie są tutoriale wyjaśniające to jakoś prościej. W każdym razie ważne, że działa.

W jawie też możesz napisać:
int surname=8;
albo
String surname="8";
Jeżeli chcesz ograniczyć string w XSD to masz do dyspozycji typ wyliczeniowy albo wyrażenia regularne (np. żeby nie zawierał cyfr). Ja w tym działaniu sprzeczności nie widzę. Łańcuchy składające się z cyfr można konwertować na typ Integer (new Integer(String s) ), ale nie każdy łańcuch znakowy będzie oznaczał liczbę.

0

dzieki! juz obczailam i patterny i inne restrykcje ktorych szukalam. Na prawde bardzo mi pomogles!

pzdr i milego dnia :)

 misty
0

wiesz co,wlasciwie to mam jeszcze jedno male pytanie. tzn zauwazylam ze jesli uzwam sequence, a tem definiuje elemnty to mam dostpne wiecej opcji. Ale jesli np mam:

<Person>3</Person>
 

czyli Person nie zawiera zadnych tagow wewnatrz, ma po prostu wartosc = 3. W xsd zdefinuje go:

 
	<xs:element name="Person">
		<xs:simpleType>
			<xs:restriction base="xs:integer">
				<xs:pattern value="[0-9]" />
			</xs:restriction>
		</xs:simpleType>
	</xs:element>

i teraz chcialabym zdefiniowac ilosc jego wystepowan, tzn minOccurs i maxOccurs, ale widze ze to jest dostepne tylko z poziomu

 		<xs:sequence>
				<xs:element

Czy ja moge (chyba powinnam moc) taki element zdefiniowac ze jest wymagany, po prostu musi byc? no albo wlasnie ze musi wystapic 2 razy, etc?

0
 <xs:element name="Person" minOccurs="1" maxOccurs="100">
                <xs:simpleType>
                        <xs:restriction base="xs:integer">
                                <xs:pattern value="[0-9]" />
                        </xs:restriction>
                </xs:simpleType>
        </xs:element>

Tyle, że w twoim przykładzie Person jest korzeniem dokumentu, bo w schemacie nie ma innego elementu, który by mógł pełnić taką rolę. Korzeń może być tylko jeden, więc nie możesz powtórzyć.
Rozwiązaniem jest zdefiniowanie nowego elementu, np. Personas i określenie jego typu jako sekwencji elementów Person. Wtedy definicja elementu Person będzie wewnątrz sekwencji i atrybuty określające ilość wystąpień będą dozwolone.
Jeżeli dobrze zrozumiałem co chcesz osiągnąć...

0

tak! dzieki :)

0

to znow ja :)

a powiedz mi jeszcze, czy kolejnosc tagow ma znaczenie aby xml byl poprawny? np:

<SuperTag>
<Person>PP</Person>
<Test>TT</Test>
<Person>AA</Person>
</SuperTag>
 

czyli, w xml'u jest wpierw Person, potem Test, potem Person. Czy taki xml jest ok? Bo (z tego jak rozumiem) zachowane musi byc dla xsd to, ze znajduja sie one w <SuperTag>. tzn, chodzi mi o to ze majac taka defincje w xsd:

 
<xs:element name="SuperTag" minOccurs="1" maxOccurs="1">
	<xs:complexType>
		<xs:sequence>
			<xs:element name="Person" minOccurs="1" >
				<xs:simpleType>
					<xs:restriction base="xs:string">
						<xs:pattern value="[A-Z][A-Z]" />
						</xs:restriction>
					</xs:simpleType>
			</xs:element>
			<xs:element name="Test" minOccurs="1" maxOccurs="1">
			      <xs:simpleType>
					<xs:restriction base="xs:string">
						<xs:pattern value="[A-Z][A-Z]" />
							</xs:restriction>
						</xs:simpleType>
				</xs:element>
			</xs:sequence>
			</xs:complexType>
		</xs:element>

no i tak to mi rzuca blad, nie pasuje mu kolejnosc. oczywiscie jak recznie "uporzadkuje" xmla:

<SuperTag>
<Person>PP</Person>
<Person>AA</Person>
<Test>TT</Test>
</SuperTag>
 

to wszystko bedzie ok. tyle ze xml jest generowany.. i teraz moje pytanie jest takie - czy mozna jakos, przy pomocy czegos (czego?) zdefiniowac w xsd ze w obrebie tagu SuperTag elementy nie musza byc po kolei? Czy niestety nie da sie, to by oznaczalo nieporawny xml i ja po stronie generatora musze zadbac o to by byla zachowana kolejnosc?

 pzdr,
     misty
0

zamiast sequence zainteresuj się all

Jeśli chcesz jednak mieć dwa elementy person to nie przejdzie w all.

0

all juz probowalam i tez nie dziala..

0

<xs:element name="superTag">
xs:complexType
xs:all
<xs:element type="xs:string" name="TEST"/>

    <xs:element name="PersonSS">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="PERSON" maxOccurs="unbounded" minOccurs="1">
            <xs:complexType>
              <xs:all>
                <xs:element type="xs:string" name="imie"/>
                <xs:element type="xs:string" name="nazwisko"/>
              </xs:all>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:all>
</xs:complexType>

</xs:element>

Można opakować person w jakiś wyższy element - tu: PersonSS. Kolejność w tym wypadku nie jest ważna, jedyne co to w tej chwili TEST (oraz PersonSS: ale w środku już Person może występować ile chce ;) ) wystąpić może raz. Nie wiem co tam chciałabyś umieścić więc taki przykład wyciągniety z mojego kodu

0

hej, dzieki za przyklad. Ale dokopalam sie do: xs:choice - zamiast xs:sequence i dziala jak chcialam. tzn nie musi byc zachowany order..

pzdr!

0

A czy ktos z Was wie moze jak moglabym uzyc dwukropka w xs:element name? tzn np:

<xs:element name="moj:przyklad" />
 

W dokumentacji napisane jest ze name nie moze miec dwukropka. Ale czy tego nie da sie w jakis sposob (jaki?) obejsc?

pzdr,
misty

0

Skoro nawet w dokumentacji piszą, że nie można, to pewnie nie można i lepiej się do tego zastosować. Z drugiej strony brak tego znaku wcale tak mocno nie ogranicza nazewnictwa tagów, bo w tagach to on jak najbardziej może być. Wspominałem wcześniej, że XML może mieć przestrzeń nazw. Żeby nie pisać jej wszędzie definiuje się tzw. prefiks i podaje się go przed nazwą elementu (w XML). Nadawanie prefiksów jest na tyle elastyczne, że nie muszą one być definiowane w schemacie, bo tutaj przestrzeń nazw określa atrybut targetNamespace. Przykładowo XML może być taki:

 <?xml version="1.0" encoding="UTF-8"?>
<Person xmlns="http://www.example.org/test">
        <name>name</name>
        <surname>surname</surname>
</Person>

albo ten sam XML:

 <?xml version="1.0" encoding="UTF-8"?>
<moj:Person xmlns:moj="http://www.example.org/test">
        <moj:name>name</moj:name>
        <moj:surname>surname</moj:surname>
</moj:Person>

albo nawet tak:

 <?xml version="1.0" encoding="UTF-8"?>
<moj:Person xmlns:moj="http://www.example.org/test" xmlns="http://www.example.org/test">
        <name>name</name>
        <surname>surname</surname>
</moj:Person>

Wszystkie 3 są dla parsera równoważne.

0

hej, no wlasnie zapomnialam sie odezwac ze obkumalam przestrzenie nazw. Dziala jak chcialam, dzieki! pzdr

0

hej, napotkalam na kolejny problem postanowilam wiec pociagnac watek. Chce napisac xsd na podstawie ktorego wygeneruje xml'a w ktorym rozne elementy beda przypisane do roznych przestrzeni nazw (i beda mialy odpowiednie przedrostki). Normalnie nie jest to takie trudne, ale.. Mam 2 pliki: Main.xsd oraz Child.xsd ktory jest importowany do Main.xsd. Wszystko co jest w Main chce by mialo przedrostek "main:", zas to co jest z Child, by mialo przedrostek "child:". Mam to tak:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://mytest/Main" 
xmlns:main="http://mytest/Main" 
elementFormDefault="qualified" 
xmlns:child="http://mytest/Child">
	<xs:import namespace="http://mytest/Child" schemaLocation="Child.xsd" />
	<xs:element name="Main">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="MainHead" />
				<xs:element name="MainBody">
					<xs:complexType>
						<xs:sequence>
							<xs:element name="Child" type="child:Child" />
						</xs:sequence>
					</xs:complexType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema> 
 <?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://mytest/Child" xmlns:child="http://mytest/Child" elementFormDefault="qualified">
	<xs:complexType name="Child">
		<xs:sequence>
			<xs:element name="ChildName" />
			<xs:element name="ChildSurname" />
		</xs:sequence>
	</xs:complexType>
</xs:schema>

ale na podstawie tego moj xml bedzie wygladal tak:

 <?xml version="1.0" encoding="UTF-8"?>
<main:Main xmlns:child="http://mytest/Child" xmlns:main="http://mytest/Main" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mytest/Main Main.xsd ">
  <main:MainHead/>
  <main:MainBody>
    <main:Child>
      <child:ChildName/>
      <child:ChildSurname/>
    </main:Child>
  </main:MainBody>
</main:Main>

a ja chce by w Child mial:

 
<child:Child>
    <child:ChildName/>
      <child:ChildSurname/>
</child:Child>

i z tym jest problem, bo Child jest zdefiniowany w Main.. i dlatego ma pewnie ten prrefix "main:". Czy ja moge cos z tym zrobic by ten element mial przedrosetek "child:"?

pzdr,
misty

1

Musisz w schemacie Child.xsd zdefiniować element Child i użyć go w schemacie Main.xsd mniej więcej tak:

<xs:element name="MainBody">
                                        <xs:complexType>
                                                <xs:sequence>
                                                        <xs:element ref="child:Child" />
                                                </xs:sequence>
                                        </xs:complexType>
                                </xs:element>
0

o jaaa, pomoglo, dzieki :) Musze przyznac ze na prawde masz sporo wiedzy w tym temacie! :)

pzdr,
misty

1 użytkowników online, w tym zalogowanych: 0, gości: 1