XSD generator
Derive an XML schema from one example document — and read, line by line, which parts were measured and which were guessed.
- SECURE
- NO UPLOADS
- NO SIGNUP
- BROWSER BASED
- FREE
- FOREVER.
Support us with a link or a share
The schema appears here as you paste or open an XML document.
What an XSD generator can and cannot know
Deriving a schema from an example is guessing with a good method. The document in front of the tool is one sample of a format, and a sample cannot tell you the rules — it can only tell you that these particular rules were not broken this particular time. Every generator on the first page of results does the guessing. What none of them do is say which parts were guessed.
That is the whole difference here. Anything this page could actually observe is written into the schema as a fact. Anything it had to assume is listed beside the schema with the path it applies to, what was seen there, and what the schema now claims as a result. You can read it in about thirty seconds and know exactly which three lines to check against a second document.
Why your number came out as a string
Because it had a leading zero. 007, 01606 and
00449 are all perfectly valid integers as far as XML is concerned, and they
are all part numbers, zip codes or account references as far as everyone else is
concerned. Type one of them xs:integer and every document validated against
that schema afterwards loses its leading zeros — silently, in whatever consumes the data
next, which is the worst place to find out.
So the rule is: digits with a leading zero are xs:string, and the tool says
it did that. A plain 0 is a number, and so is 0.5 — the zero
carries no information in either. The same conservatism applies to 1 and
0, which are valid xs:boolean as well as valid
xs:integer. Guessing boolean there would turn every counter in every document
into a flag, so it does not guess: only the literal words true and
false get the boolean type.
Dates get the same treatment from the other direction. A string shaped like
2026-02-30 matches the pattern of an xs:date and is not one,
because February has no thirtieth. It is typed as a string, and a real date such as
2024-02-29 is not.
minOccurs is measured where it can be, and admitted where it cannot
This is the inference that goes wrong most often and gets explained least. A single
document can only demonstrate that something is optional where its parent repeats. If a
catalog holds five books and three of them carry an ISBN, then
minOccurs="0" on that ISBN is a measurement — the document showed you two
books without one.
If the catalog holds one book, and that book carries an ISBN, absolutely nothing has been
shown. The schema still has to say something, so it says
minOccurs="1" maxOccurs="1", and the tool puts that path in the guessed list
rather than letting it pass as a fact. The same logic covers attributes: a
use="required" derived from an element that only ever appeared once is a
guess, and it is labeled as one.
The practical consequence is that a better example beats a better generator. Two records where one omits an optional field will teach this page more than a thousand identical ones.
When the order of children is not fixed
An xs:sequence says the children appear in exactly this order. If two sibling
elements in your document disagree about the order — one has first name then surname, the
other the reverse — then a sequence would be a claim the document itself disproves, and the
source file would fail its own schema.
There is no clean way out of this in XSD 1.0. xs:all allows any order but
cannot carry maxOccurs, so it is useless for a repeating group. What this page
emits instead is a repeating xs:choice, which accepts any order and any number
of children. It is honest and it is weak, and the tool says so, because it is the one part
of a derived schema most likely to need editing by hand.
Russian Doll, and why the other two designs are not offered
Schema authors talk about three styles. Russian Doll nests every
definition inside one global element. Salami Slice declares every element
globally and refers to them with ref. Venetian Blind names
the complex types and keeps a single global element.
Only the first can be derived honestly from one document, and that is a consequence rather
than a preference. The other two require an element name to have one definition
across the whole schema — and real documents break that constantly. A
<name> inside <author> is a string; a
<name> inside <publisher> may have children of its
own. Producing a Salami Slice or Venetian Blind schema from that example means merging two
definitions the document never showed to be the same thing, which is an assumption
wearing the clothes of a design choice. Russian Doll defines each element where it stands,
so the two stay separate.
Namespaces, and the one thing this refuses to do
A document in a single namespace becomes a schema with that
targetNamespace and elementFormDefault="qualified", which is what
almost every real vocabulary uses. Attributes stay unqualified, because that is how
almost every real vocabulary writes them.
A document using more than one namespace gets a refusal instead of a schema, and the
refusal names the namespaces it found. A schema document has exactly one target namespace,
so describing such a file correctly needs one schema per namespace joined with
xs:import — and how you want those files split is a decision about your
project, not something an example document can settle. An invented answer would be worse
than no answer. Attributes in the xsi namespace, including
xsi:schemaLocation, are ignored rather than turned into required attributes,
because a validator allows them everywhere already.
Check the schema, do not trust it
Every schema this page writes is one it believes accepts the document it came from, and the belief is tested: the test suite runs each generated schema against its own source through libxml2 and requires a clean result, then mutates the source so that a field carries the wrong type and requires the same schema to reject it. That is a claim about the generator, though, not about your file.
For your file, take the schema next door. The XML validator runs libxml2 in the browser and will tell you what it thinks of the pair — and, far more useful, what it thinks of the next document that arrives from the same source. If the document needs tidying before you can read what it contains, the XML formatter lays it out first, and the XPath tester is the quickest way to find out whether the element you think is repeating actually is.
Nothing here leaves the tab
XML that needs a schema is rarely decorative. It is an integration payload, an invoice batch, a health record export, a bank statement, a government filing — the kind of document whose whole point is that it moves between two organizations under an agreement. Pasting one into an unknown page to get a schema out is a habit worth breaking.
The parser here runs in this tab, no DTD is fetched, no external entity is resolved, and an
xsi:schemaLocation is read as text rather than opened. You can watch it: open
your browser's network panel and then paste your document. Nothing appears, because there
is nowhere for a request to go.
Questions
Can an XSD generator really work from one XML file?
It can produce a schema, and that schema will accept the document it came from. What it cannot do is know the rules of the format — one document is a sample. This tool separates the two: anything it could observe is stated as fact, and anything it had to assume appears in a list with the path, what was seen and what the schema now claims.
Why is my number typed as a string?
Because it had a leading zero. A value like 007 or 01606 is a valid integer to XML and a part number, zip code or account number to everyone else, and typing it xs:integer would silently drop the zeros from every document validated against the schema afterwards. Plain 0 and 0.5 are typed as numbers — the zero carries no information there.
Why does it say minOccurs cannot be known?
Because a single document can only show absence where a parent repeats. If five books appear and three carry an ISBN, minOccurs="0" is a measurement. If a book appears once and carries an ISBN, nothing at all has been shown, and minOccurs="1" is a guess — so it is listed as one instead of passing as a fact.
Which schema design style does it use?
Russian Doll — everything nested inside one global element — and that is a consequence rather than a preference. Salami Slice and Venetian Blind both require an element name to have a single definition across the whole schema, and real documents break that constantly: a name element inside author is a string, while a name inside publisher may have children of its own. Deriving those two from one example means merging definitions the document never showed to be the same.
Does my XML leave the browser?
No. The parser runs in this tab, no DTD or external entity is fetched, and an xsi:schemaLocation in your document is read as text and never opened. XML that needs a schema is usually an integration payload, an invoice or an export, which is exactly the kind of file that should not be pasted into a stranger.