2 using System
.Reflection
;
4 using System
.Xml
.Schema
;
5 using Commons
.Xml
.Relaxng
;
6 using Commons
.Xml
.Relaxng
.Rnc
;
8 using BF
= System
.Reflection
.BindingFlags
;
10 namespace Mono
.XmlTools
14 public static int Main (string [] args
)
16 if (args
.Length
== 0) {
21 return new Dtd2Rng ().Process (args
);
26 Console
.Error
.WriteLine (@"
27 Usage dtd2rng [options] dtdfile [ns]
30 --help : show this message.
31 --compact, -c : output compact syntax.
35 public int Process (string [] args
)
39 string ns
= String
.Empty
;
40 foreach (string arg
in args
) {
41 if (arg
== "--help") {
45 if (arg
== "--compact" || arg
== "-c")
47 else if (file
== null)
49 else if (ns
!= String
.Empty
) {
51 Console
.Error
.WriteLine ("Extra command line argument.");
59 if (file
.EndsWith (".dtd")) {
60 xtr
= new XmlTextReader (
61 "<!DOCTYPE dummy SYSTEM '" + file
+ "'>",
62 XmlNodeType
.Document
, null);
64 xtr
= new XmlTextReader (file
);
67 if (xtr
.NodeType
== XmlNodeType
.XmlDeclaration
)
70 XmlSchema xsd
= GetXmlSchema (xtr
);
72 RelaxngPattern rng
= DtdXsd2Rng (xsd
, ns
);
74 rng
.WriteCompact (Console
.Out
);
76 XmlTextWriter w
= new XmlTextWriter (Console
.Out
);
77 w
.Formatting
= Formatting
.Indented
;
84 XmlSchema
GetXmlSchema (XmlTextReader xtr
)
86 // Hacky reflection part
88 BF flag
= BF
.NonPublic
| BF
.Instance
;
90 // In Mono NET_2_0 XmlTextReader is just a wrapper which
91 // does not contain DTD directly.
92 FieldInfo fi
= typeof (XmlTextReader
).GetField ("source", flag
);
94 impl
= fi
.GetValue (xtr
);
96 PropertyInfo pi
= impl
.GetType ().GetProperty ("DTD", flag
);
97 object dtd
= pi
.GetValue (impl
, null);
99 dtd
.GetType ().GetMethod ("CreateXsdSchema", flag
);
100 object o
= mi
.Invoke (dtd
, null);
101 return (XmlSchema
) o
;
106 RelaxngGrammar
DtdXsd2Rng (XmlSchema xsd
, string ns
)
108 g
= new RelaxngGrammar ();
109 g
.DefaultNamespace
= ns
;
110 RelaxngStart start
= new RelaxngStart ();
111 g
.Starts
.Add (start
);
112 RelaxngChoice choice
= new RelaxngChoice ();
113 start
.Pattern
= choice
;
115 // There are only elements.
116 foreach (XmlSchemaElement el
in xsd
.Items
) {
117 RelaxngDefine def
= DefineElement (el
);
119 RelaxngRef dref
= new RelaxngRef ();
120 dref
.Name
= def
.Name
;
121 choice
.Patterns
.Add (dref
);
127 RelaxngDefine
DefineElement (XmlSchemaElement el
)
129 RelaxngDefine def
= new RelaxngDefine ();
130 def
.Patterns
.Add (CreateElement (el
));
136 RelaxngPattern
CreateElement (XmlSchemaElement xse
)
138 if (xse
.RefName
!= XmlQualifiedName
.Empty
) {
139 RelaxngRef r
= new RelaxngRef ();
140 r
.Name
= xse
.RefName
.Name
;
141 // namespace means nothing here.
145 RelaxngElement re
= new RelaxngElement ();
146 RelaxngName name
= new RelaxngName ();
147 name
.LocalName
= xse
.Name
;
150 XmlSchemaComplexType ct
= xse
.SchemaType
as XmlSchemaComplexType
;
152 foreach (XmlSchemaAttribute a
in ct
.Attributes
)
153 re
.Patterns
.Add (CreateAttribute (a
));
155 RelaxngPattern rpart
;
156 if (ct
.Particle
== null)
157 rpart
= new RelaxngEmpty ();
159 rpart
= CreatePatternFromParticle (ct
.Particle
);
162 if (rpart
.PatternType
!= RelaxngPatternType
.Empty
) {
163 RelaxngMixed mixed
= new RelaxngMixed ();
164 mixed
.Patterns
.Add (rpart
);
167 rpart
= new RelaxngText ();
171 re
.Patterns
.Add (rpart
);
176 RelaxngPattern
CreateAttribute (XmlSchemaAttribute attr
)
178 RelaxngAttribute ra
= new RelaxngAttribute ();
179 RelaxngName name
= new RelaxngName ();
180 name
.LocalName
= attr
.Name
;
182 ra
.Pattern
= attr
.SchemaType
!= null ?
183 CreatePatternFromType (attr
.SchemaType
) :
184 CreatePatternFromTypeName (attr
.SchemaTypeName
);
186 RelaxngPattern ret
= ra
;
188 if (attr
.Use
== XmlSchemaUse
.Optional
) {
189 RelaxngOptional opt
= new RelaxngOptional ();
190 opt
.Patterns
.Add (ra
);
196 RelaxngPattern
CreatePatternFromParticle (XmlSchemaParticle xsdp
)
198 RelaxngSingleContentPattern rngp
= null;
199 if (xsdp
.MinOccurs
== 0 && xsdp
.MaxOccursString
== "unbounded")
200 rngp
= new RelaxngZeroOrMore ();
201 else if (xsdp
.MinOccurs
== 1 && xsdp
.MaxOccursString
== "unbounded")
202 rngp
= new RelaxngOneOrMore ();
203 else if (xsdp
.MinOccurs
== 0)
204 rngp
= new RelaxngOptional ();
206 RelaxngPattern child
= CreatePatternFromParticleCore (xsdp
);
209 rngp
.Patterns
.Add (child
);
213 RelaxngPattern
CreatePatternFromParticleCore (XmlSchemaParticle xsdp
)
215 XmlSchemaGroupBase gb
= xsdp
as XmlSchemaGroupBase
;
216 if (xsdp
is XmlSchemaAny
) {
217 RelaxngRef r
= new RelaxngRef ();
221 if (gb
is XmlSchemaSequence
) {
222 RelaxngGroup grp
= new RelaxngGroup ();
223 foreach (XmlSchemaParticle xsdc
in gb
.Items
)
224 grp
.Patterns
.Add (CreatePatternFromParticle (xsdc
));
227 if (gb
is XmlSchemaChoice
) {
228 RelaxngChoice rc
= new RelaxngChoice ();
229 foreach (XmlSchemaParticle xsdc
in gb
.Items
)
230 rc
.Patterns
.Add (CreatePatternFromParticle (xsdc
));
233 return CreateElement ((XmlSchemaElement
) xsdp
);
236 RelaxngPattern
CreatePatternFromType (XmlSchemaType type
)
238 XmlSchemaSimpleType st
= type
as XmlSchemaSimpleType
;
240 throw new NotSupportedException ("Complex types are not supported as an attribute type.");
241 XmlSchemaSimpleTypeRestriction r
=
242 st
.Content
as XmlSchemaSimpleTypeRestriction
;
244 throw new NotSupportedException ("Only simple type restriction is supported as an attribute type.");
246 RelaxngChoice c
= new RelaxngChoice ();
247 foreach (XmlSchemaFacet f
in r
.Facets
) {
248 XmlSchemaEnumerationFacet en
=
249 f
as XmlSchemaEnumerationFacet
;
251 throw new NotSupportedException ("Only enumeration facet is supported.");
252 RelaxngValue v
= new RelaxngValue ();
253 v
.Type
= r
.BaseTypeName
.Name
;
254 v
.DatatypeLibrary
= RemapDatatypeLibrary (
255 r
.BaseTypeName
.Namespace
);
262 RelaxngPattern
CreatePatternFromTypeName (XmlQualifiedName name
)
264 if (name
== XmlQualifiedName
.Empty
)
265 return new RelaxngText ();
266 RelaxngData data
= new RelaxngData ();
267 data
.Type
= name
.Name
;
268 data
.DatatypeLibrary
= RemapDatatypeLibrary (
273 string RemapDatatypeLibrary (string ns
)
275 return ns
== XmlSchema
.Namespace
?
276 "http://www.w3.org/2001/XMLSchema-datatypes" :