Class RELAXNGWriter
- java.lang.Object
-
- com.sun.msv.writer.relaxng.RELAXNGWriter
-
- All Implemented Interfaces:
GrammarWriter
,Context
public class RELAXNGWriter extends java.lang.Object implements GrammarWriter, Context
converts any Grammar into RELAX NG XML representation through SAX1 events.How it works
Grammar
object can be thought as a (possibly) cyclic graph made fromExpression
. For example, the following simple TREX pattern will be represented as following AGM.abc abc Note that
- sub expressions are shared (see <string> expression).
- there is a cycle in the graph.
- several syntax elements are replaced by others (e.g., <optional>P</optional> -> <choice><empty/>P</choice>)
To write these expressions into TREX XML representation, we have to take care of cycles, since cyclic references cannot be written into XML without first cut it and use <ref>/<define> pair.
First, this algorithm splits the grammar into "islands". Island is a tree of expressions; it has a head expression and most importantly it doesn't contain any cycles in it. Member of an island can be always reached from its head.
TREXWriter will make every
ElementExp
andReferenceExp
a head of their own island. So each of them has their own island.It is guaranteed that this split will always give islands without inner cycles. Several islands can form a cycle, but one island can never have a cycle in it. This is because there is always at least one ElementExp in any cycle.
Note that since expressions are shared, one expression can be a member of several islands (although this isn't depicted in the above figure.)
Then, this algorithm merges some islands. For example, island E is referenced only once (from island D). This means that there is no need to give a name to this pattern. Instead, island E can simply written as a subordinate of island D.
In other words, any island who is only referenced at most once is merged into its referer. This step makes the output more compact.
Next, TREXWriter assigns a name to each island. It tries to use the name of the head expression. If a head is anonymous ReferenceExp (ReferenceExp whose name field is
null
) or there is a name conflict, TREXWriter will add some suffix to make the name unique.Finally, each island is written as one named pattern under <define> element. All inter-island references are replaced by <ref> element.
Why SAX1?
Due to the bug and insufficient supports for the serialization through SAX2, The decision is made to use SAX1. SAX1 allows us to control namespace prefix mappings better than SAX2.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) class
RELAXNGWriter.SmartPatternWriter
PatternWriter that performs some optimization for human eyes.
-
Field Summary
Fields Modifier and Type Field Description protected java.lang.String
defaultNs
namespace URI currently implied through "ns" attribute propagation.protected java.util.Map
exp2name
map from ReferenceExp/ElementExp to its unique name.protected Grammar
grammar
Grammar object which we are writing.protected NameClassVisitor
nameClassWriter
protected RELAXNGWriter.SmartPatternWriter
patternWriter
protected XMLWriter
writer
-
Constructor Summary
Constructors Constructor Description RELAXNGWriter()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description protected NameClassVisitor
createNameClassWriter()
java.lang.String
getTargetNamespace()
XMLWriter
getWriter()
void
setDocumentHandler(org.xml.sax.DocumentHandler handler)
Sets DocumentHandler.protected java.lang.String
sniffDefaultNs(Expression exp)
sniffs namespace URI that can be used as default 'ns' attribute from expression.void
write(Grammar g)
Converts this grammar to the XML representation.void
write(Grammar g, java.lang.String _defaultNs)
generates SAX2 events of the specified grammar.protected void
writeIsland(Expression exp)
writes a bunch of expression into one tree.void
writeNameClass(NameClass src)
-
-
-
Field Detail
-
writer
protected XMLWriter writer
-
grammar
protected Grammar grammar
Grammar object which we are writing.
-
exp2name
protected java.util.Map exp2name
map from ReferenceExp/ElementExp to its unique name. "unique name" is used to write/reference this ReferenceExp. ReferenceExps who are not in this list can be directly written into XML.
-
defaultNs
protected java.lang.String defaultNs
namespace URI currently implied through "ns" attribute propagation.
-
nameClassWriter
protected NameClassVisitor nameClassWriter
-
patternWriter
protected RELAXNGWriter.SmartPatternWriter patternWriter
-
-
Method Detail
-
setDocumentHandler
public void setDocumentHandler(org.xml.sax.DocumentHandler handler)
Description copied from interface:GrammarWriter
Sets DocumentHandler. This handler will receive the result of conversion.- Specified by:
setDocumentHandler
in interfaceGrammarWriter
-
write
public void write(Grammar g) throws org.xml.sax.SAXException
Description copied from interface:GrammarWriter
Converts this grammar to the XML representation.- Specified by:
write
in interfaceGrammarWriter
- Throws:
org.xml.sax.SAXException
- DocumentHandler may throw a SAXException.
-
write
public void write(Grammar g, java.lang.String _defaultNs) throws org.xml.sax.SAXException
generates SAX2 events of the specified grammar.- Parameters:
defaultNs
- if specified, this namespace URI is used as "ns" attribute of grammar element. Can be null.- Throws:
java.lang.IllegalArgumentException
- If the given grammar is beyond the expressive power of TREX (e.g., some RELAX NG grammar), then this exception is thrown.org.xml.sax.SAXException
-
writeIsland
protected void writeIsland(Expression exp)
writes a bunch of expression into one tree.
-
sniffDefaultNs
protected java.lang.String sniffDefaultNs(Expression exp)
sniffs namespace URI that can be used as default 'ns' attribute from expression. find an element or attribute, then use its namespace URI.
-
getTargetNamespace
public java.lang.String getTargetNamespace()
- Specified by:
getTargetNamespace
in interfaceContext
-
writeNameClass
public void writeNameClass(NameClass src)
- Specified by:
writeNameClass
in interfaceContext
-
createNameClassWriter
protected NameClassVisitor createNameClassWriter()
-
-