Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Eno <atsushieno@gmail.com>2005-03-23 17:08:32 +0300
committerAtsushi Eno <atsushieno@gmail.com>2005-03-23 17:08:32 +0300
commit9e00749d20857e7e79eee08a3b3c212cb2cfbe26 (patch)
tree0b2be2516be319d5b67d81091f2691d6f8266a4c /mcs/class/System.XML/Mono.Xml.Xsl
parent6c50b75585a9a636ffacbfb6a216da0dd8187cf8 (diff)
2005-03-23 Atsushi Enomoto <atsushi@ximian.com>
* XslStylesheet.cs : Variables are stored per stylesheet and added to compiler after all of the contents are processed (handle import precedence). Imports are now processed in prior to other contents (incorrect imports are now rejected). After imports, process includes to process nested imports. In-process included stylesheets are temporarily stored in including stylesheet. Handle keys like variables are handled. Added Compile() that is splitted from .ctor(). * Compiler.cs : Store keys in compiler and compiled stylesheet. Duplicate variables in imports are now overriden as expected. * XsltCompiledContext.cs : use CompiledStylesheet.ResolveKey(). svn path=/trunk/mcs/; revision=42144
Diffstat (limited to 'mcs/class/System.XML/Mono.Xml.Xsl')
-rw-r--r--mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog16
-rw-r--r--mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs30
-rw-r--r--mcs/class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs171
-rw-r--r--mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs2
4 files changed, 167 insertions, 52 deletions
diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog b/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog
index d96590bb1f9..a8bb59ab0a0 100644
--- a/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog
+++ b/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog
@@ -1,3 +1,19 @@
+2005-03-23 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XslStylesheet.cs :
+ Variables are stored per stylesheet and added to compiler after
+ all of the contents are processed (handle import precedence).
+ Imports are now processed in prior to other contents (incorrect
+ imports are now rejected). After imports, process includes to
+ process nested imports. In-process included stylesheets are
+ temporarily stored in including stylesheet.
+ Handle keys like variables are handled.
+ Added Compile() that is splitted from .ctor().
+ * Compiler.cs :
+ Store keys in compiler and compiled stylesheet.
+ Duplicate variables in imports are now overriden as expected.
+ * XsltCompiledContext.cs : use CompiledStylesheet.ResolveKey().
+
2005-03-22 Atsushi Enomoto <atsushi@ximian.com>
* XslTransformProcessor.cs : now it looks safe to remove SetContext()
diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs b/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs
index 6787b9f5a3f..2c55e1b43c1 100644
--- a/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs
+++ b/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs
@@ -97,6 +97,11 @@ namespace Mono.Xml.Xsl
return (XslGeneralVariable)globalVariables [name];
}
+ public XslKey ResolveKey (QName name)
+ {
+ return (XslKey) keys [name];
+ }
+
public XslAttributeSet ResolveAttributeSet (QName name)
{
return (XslAttributeSet)attrSets [name];
@@ -112,6 +117,7 @@ namespace Mono.Xml.Xsl
Stack styleStack = new Stack ();
XslStylesheet currentStyle;
+ Hashtable keys = new Hashtable ();
Hashtable globalVariables = new Hashtable ();
Hashtable attrSets = new Hashtable ();
@@ -150,14 +156,15 @@ namespace Mono.Xml.Xsl
nav.MoveToParent ();
}
try {
- this.rootStyle = new XslStylesheet (this);
+ rootStyle = new XslStylesheet ();
+ rootStyle.Compile (this);
} catch (XsltCompileException) {
throw;
} catch (Exception x) {
throw new XsltCompileException ("XSLT compile error. " + x.Message, x, Input);
}
- return new CompiledStylesheet (rootStyle, globalVariables, attrSets, exprStore, nsMgr, rootStyle.Keys, outputs, decimalFormats, msScripts);
+ return new CompiledStylesheet (rootStyle, globalVariables, attrSets, exprStore, nsMgr, keys, outputs, decimalFormats, msScripts);
}
MSXslScriptManager msScripts = new MSXslScriptManager ();
@@ -220,7 +227,7 @@ namespace Mono.Xml.Xsl
}
}
- private void PushInputDocument (XPathNavigator nav)
+ public void PushInputDocument (XPathNavigator nav)
{
// Inclusion nest check
IXmlLineInfo li = currentInput as IXmlLineInfo;
@@ -392,7 +399,12 @@ namespace Mono.Xml.Xsl
{
globalVariables [var.Name] = var;
}
-
+
+ public void AddKey (XslKey key)
+ {
+ keys [key.Name] = key;
+ }
+
public void AddAttributeSet (XslAttributeSet set)
{
XslAttributeSet existing = attrSets [set.Name] as XslAttributeSet;
@@ -598,6 +610,7 @@ namespace Mono.Xml.Xsl
}
internal class VariableScope {
+ ArrayList variableNames;
Hashtable variables;
VariableScope parent;
int nextSlot = 0;
@@ -622,10 +635,15 @@ namespace Mono.Xml.Xsl
public int AddVariable (XslLocalVariable v)
{
- if (variables == null)
+ if (variables == null) {
+ variableNames = new ArrayList ();
variables = new Hashtable ();
-
+ }
variables [v.Name] = v;
+ int idx = variableNames.IndexOf (v.Name);
+ if (idx >= 0)
+ return idx;
+ variableNames.Add (v.Name);
return nextSlot++;
}
diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs b/mcs/class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs
index 26d834d60c9..31b4d284e67 100644
--- a/mcs/class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs
+++ b/mcs/class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs
@@ -59,6 +59,8 @@ namespace Mono.Xml.Xsl {
Hashtable parameters = new Hashtable ();
// [QName]=>XslKey
Hashtable keys = new Hashtable();
+ // [QName]=>XslVariable
+ Hashtable variables = new Hashtable ();
XslTemplateTable templates;
@@ -68,6 +70,11 @@ namespace Mono.Xml.Xsl {
XmlQualifiedName [] excludeResultPrefixes;
ArrayList stylesheetNamespaces = new ArrayList ();
+ // in-process includes. They must be first parsed as
+ // XPathNavigator, collected imports, and then processed
+ // other content.
+ Hashtable inProcessIncludes = new Hashtable ();
+
public XmlQualifiedName [] ExtensionElementPrefixes {
get { return extensionElementPrefixes; }
}
@@ -100,15 +107,15 @@ namespace Mono.Xml.Xsl {
get { return templates; }
}
- public Hashtable Keys {
- get { return keys; }
- }
-
public string Version {
get { return version; }
}
- public XslStylesheet (Compiler c)
+ public XslStylesheet ()
+ {
+ }
+
+ internal void Compile (Compiler c)
{
c.PushStylesheet (this);
@@ -123,7 +130,7 @@ namespace Mono.Xml.Xsl {
if (c.Input.GetAttribute ("version", XsltNamespace) == String.Empty)
throw new XsltCompileException ("Mandatory global attribute version is missing.", null, c.Input);
// then it is simplified stylesheet.
- Templates.Add (new XslTemplate (c));
+ templates.Add (new XslTemplate (c));
} else {
if (c.Input.LocalName != "stylesheet" &&
c.Input.LocalName != "transform")
@@ -145,8 +152,14 @@ namespace Mono.Xml.Xsl {
}
ProcessTopLevelElements (c);
}
-
+
+ foreach (XslGlobalVariable v in variables.Values)
+ c.AddGlobalVariable (v);
+ foreach (XslKey key in keys.Values)
+ c.AddKey (key);
+
c.PopStylesheet ();
+ inProcessIncludes = null;
}
private QName [] ParseMappedPrefixes (string list, XPathNavigator nav)
@@ -168,19 +181,6 @@ namespace Mono.Xml.Xsl {
return (QName []) al.ToArray (typeof (QName));
}
- public XslKey FindKey (QName name)
- {
- XslKey key = Keys [name] as XslKey;
- if (key != null)
- return key;
- for (int i = Imports.Count - 1; i >= 0; i--) {
- key = ((XslStylesheet) Imports [i]).FindKey (name);
- if (key != null)
- return key;
- }
- return null;
- }
-
bool countedSpaceControlExistence;
bool cachedHasSpaceControls;
static readonly QName allMatchName = new QName ("*");
@@ -319,36 +319,81 @@ namespace Mono.Xml.Xsl {
return result != null ? result : prefix;
}
- private XslStylesheet (Compiler c, XslStylesheet importer) : this (c)
+ private void StoreInclude (Compiler c)
{
-// this.importer = importer;
+ XPathNavigator including = c.Input.Clone ();
+ c.PushInputDocument (c.Input.GetAttribute ("href", String.Empty));
+ inProcessIncludes [including] = c.Input;
+
+ HandleImportsInInclude (c);
+ c.PopInputDocument ();
}
-
- private void HandleInclude (Compiler c, string href)
+
+ private void HandleImportsInInclude (Compiler c)
{
- c.PushInputDocument (href);
+ if (c.Input.NamespaceURI != XsltNamespace) {
+ if (c.Input.GetAttribute ("version",
+ XsltNamespace) == String.Empty)
+ throw new XsltCompileException ("Mandatory global attribute version is missing.", null, c.Input);
+ // simplified style == never imports.
+ // Keep this position
+ return;
+ }
+
+ if (!c.Input.MoveToFirstChild ()) {
+ c.Input.MoveToRoot ();
+ return;
+ }
+
+ HandleIncludesImports (c);
+ }
+
+ private void HandleInclude (Compiler c)
+ {
+ XPathNavigator included = null;
+ foreach (XPathNavigator inc in inProcessIncludes.Keys) {
+ if (inc.IsSamePosition (c.Input)) {
+ included = (XPathNavigator) inProcessIncludes [inc];
+ break;
+ }
+ }
+ if (included == null)
+ throw new Exception ("Should not happen. Current input is " + c.Input.BaseURI + " / " + c.Input.Name + ", " + inProcessIncludes.Count);
+
+ if (included.NodeType == XPathNodeType.Root)
+ return; // Already done.
+
+ c.PushInputDocument (included);
- // move to root element
while (c.Input.NodeType != XPathNodeType.Element)
if (!c.Input.MoveToNext ())
- throw new XsltCompileException ("Stylesheet root element must be either \"stylesheet\" or \"transform\" or any literal element.", null, c.Input);
+ break;
- if (c.Input.NamespaceURI != XsltNamespace) {
- if (c.Input.GetAttribute ("version", XsltNamespace) == String.Empty)
- throw new XsltCompileException ("Mandatory global attribute version is missing.", null, c.Input);
+ if (c.Input.NamespaceURI != XsltNamespace &&
+ c.Input.NodeType == XPathNodeType.Element) {
// then it is simplified stylesheet.
- Templates.Add (new XslTemplate (c));
+ templates.Add (new XslTemplate (c));
+ }
+ else {
+ do {
+ if (c.Input.NodeType != XPathNodeType.Element)
+ continue;
+ Debug.EnterNavigator (c);
+ HandleTopLevelElement (c);
+ Debug.ExitNavigator (c);
+ } while (c.Input.MoveToNext ());
}
- else
- ProcessTopLevelElements (c);
+ c.Input.MoveToParent ();
c.PopInputDocument ();
}
private void HandleImport (Compiler c, string href)
{
c.PushInputDocument (href);
- imports.Add (new XslStylesheet (c, this));
+ XslStylesheet imported = new XslStylesheet ();
+ imported.Compile (c);
+ imports.Add (imported);
c.PopInputDocument ();
}
@@ -358,14 +403,10 @@ namespace Mono.Xml.Xsl {
switch (n.NamespaceURI)
{
case XsltNamespace:
-
switch (n.LocalName)
{
case "include":
- HandleInclude (c, c.GetAttribute ("href"));
- break;
- case "import":
- HandleImport (c, c.GetAttribute ("href"));
+ HandleInclude (c);
break;
case "preserve-space":
AddSpaceControls (c.ParseQNameListAttribute ("elements"), XmlSpace.Preserve, n);
@@ -383,7 +424,8 @@ namespace Mono.Xml.Xsl {
break;
case "key":
- keys [c.ParseQNameAttribute ("name")] = new XslKey (c);
+ XslKey key = new XslKey (c);
+ keys [key.Name] = key;
break;
case "output":
@@ -398,14 +440,16 @@ namespace Mono.Xml.Xsl {
templates.Add (new XslTemplate (c));
break;
case "variable":
- c.AddGlobalVariable (new XslGlobalVariable (c));
+ XslGlobalVariable gvar = new XslGlobalVariable (c);
+ variables [gvar.Name] = gvar;
break;
case "param":
- c.AddGlobalVariable (new XslGlobalParam (c));
+ XslGlobalParam gpar = new XslGlobalParam (c);
+ variables [gpar.Name] = gpar;
break;
default:
if (version == "1.0")
- throw new XsltCompileException ("Unrecognized top level element.", null, c.Input);
+ throw new XsltCompileException ("Unrecognized top level element after imports.", null, c.Input);
break;
}
break;
@@ -419,11 +463,48 @@ namespace Mono.Xml.Xsl {
break;
}
}
-
+
+ private XPathNavigator HandleIncludesImports (Compiler c)
+ {
+ // process imports. They must precede to other
+ // top level elements by schema.
+ do {
+ if (c.Input.NodeType != XPathNodeType.Element)
+ continue;
+ if (c.Input.LocalName != "import" ||
+ c.Input.NamespaceURI != XsltNamespace)
+ break;
+ Debug.EnterNavigator (c);
+ HandleImport (c, c.GetAttribute ("href"));
+ Debug.ExitNavigator (c);
+ } while (c.Input.MoveToNext ());
+
+ XPathNavigator saved = c.Input.Clone ();
+
+ // process includes to handle nested imports. They must precede to other
+ // top level elements by schema.
+ do {
+ if (c.Input.NodeType != XPathNodeType.Element ||
+ c.Input.LocalName != "include" ||
+ c.Input.NamespaceURI != XsltNamespace)
+ continue;
+ Debug.EnterNavigator (c);
+ StoreInclude (c);
+ Debug.ExitNavigator (c);
+ } while (c.Input.MoveToNext ());
+
+ c.Input.MoveTo (saved);
+
+ return saved;
+ }
+
private void ProcessTopLevelElements (Compiler c)
{
if (!c.Input.MoveToFirstChild ())
return;
+
+ XPathNavigator saved = HandleIncludesImports (c);
+
do {
// Collect namespace aliases first.
if (c.Input.NodeType != XPathNodeType.Element ||
@@ -439,7 +520,7 @@ namespace Mono.Xml.Xsl {
namespaceAliases.Set (sprefix, rprefix);
} while (c.Input.MoveToNext ());
- c.Input.MoveToFirst ();
+ c.Input.MoveTo (saved);
do {
if (c.Input.NodeType != XPathNodeType.Element)
continue;
diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs b/mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs
index 0362b3b69bf..2984343bf16 100644
--- a/mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs
+++ b/mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs
@@ -128,7 +128,7 @@ namespace Mono.Xml.Xsl
KeyIndexTable table =
keyIndexTables [name] as KeyIndexTable;
if (table == null) {
- table = new KeyIndexTable (this, p.CompiledStyle.Style.FindKey (name));
+ table = new KeyIndexTable (this, p.CompiledStyle.ResolveKey (name));
keyIndexTables [name] = table;
}
return table;