public bool FindStylesheetElement() { if (!_topLevelReader) { if (_reader.ReadState != ReadState.Interactive) { return(false); } } // The stylesheet may be an embedded stylesheet. If this is the case the reader will be in Interactive state and should be // positioned on xsl:stylesheet element (or any preceding whitespace) but there also can be namespaces defined on one // of the ancestor nodes. These namespace definitions have to be copied to the xsl:stylesheet element scope. Otherwise it // will not be possible to resolve them later and loading the stylesheet will end up with throwing an exception. IDictionary <string, string> namespacesInScope = null; if (_reader.ReadState == ReadState.Interactive) { // This may be an embedded stylesheet - store namespaces in scope IXmlNamespaceResolver nsResolver = _reader as IXmlNamespaceResolver; if (nsResolver != null) { namespacesInScope = nsResolver.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml); } } while (MoveToNextSibling() && _nodeType == XmlNodeType.Whitespace) { ; } // An Element node was reached. Potentially this is xsl:stylesheet instruction. if (_nodeType == XmlNodeType.Element) { // If namespacesInScope is not null then the stylesheet being read is an embedded stylesheet that can have namespaces // defined outside of xsl:stylesheet instruction. In this case the namespace definitions collected above have to be added // to the element scope. if (namespacesInScope != null) { foreach (KeyValuePair <string, string> prefixNamespacePair in namespacesInScope) { // The namespace could be redefined on the element we just read. If this is the case scopeManager already has // namespace definition for this prefix and the old definition must not be added to the scope. if (_scopeManager.LookupNamespace(prefixNamespacePair.Key) == null) { string nsAtomizedValue = _atoms.NameTable.Add(prefixNamespacePair.Value); _scopeManager.AddNsDeclaration(prefixNamespacePair.Key, nsAtomizedValue); _ctxInfo.AddNamespace(prefixNamespacePair.Key, nsAtomizedValue); } } } // return true to indicate that we reached XmlNodeType.Element node - potentially xsl:stylesheet element. return(true); } // return false to indicate that we did not reach XmlNodeType.Element node so it is not a valid stylesheet. return(false); }
public ContextInfo GetAttributes(int required, int number, string[] names, string[] values) { Debug.Assert(reader.NodeType == XmlNodeType.Element); for (int i = 0; i < number; i++) { values[i] = null; } string elementName = QualifiedName; ContextInfo ctxInfo = new ContextInfo(this); compiler.EnterForwardsCompatible(); while (MoveToNextAttOrNs()) { if (nodeType == XPathNodeType.Namespace) { ctxInfo.AddNamespace(this); continue; } Debug.Assert(nodeType == XPathNodeType.Attribute); ctxInfo.AddAttribute(this); bool found = false; for (int i = 0; i < number; i++) { if (IsXsltAttribute(names[i])) { found = true; values[i] = Value; // There are only two XSL elements, xsl:stylesheet/xsl:transform and xsl:output, capable // of having 'version' attribute. And only for the first one this attribute is required. if (Ref.Equal(names[i], Atoms.Version) && i < required) { SetVersion(Value, Atoms.Version); } break; } } if (!found) { // An element from the XSLT namespace may have any attribute not from the XSLT namespace, // provided that the expanded-name of the attribute has a non-null namespace URI. // For example, it may be 'xml:space'. if (IsNullNamespace() || IsXsltNamespace()) { ReportError(/*[XT0090]*/ Res.Xslt_InvalidAttribute, QualifiedName, elementName); } } } // Ignore invalid attributes if forwards-compatible behavior is enabled. Note that invalid // attributes may encounter before ForwardCompatibility flag is set to true. For example, // <xsl:stylesheet unknown="foo" version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/> compiler.ExitForwardsCompatible(ForwardCompatibility); // Report missing mandatory attributes for (int i = 0; i < required; i++) { if (values[i] == null) { ReportError(/*[XT_001]*/ Res.Xslt_MissingAttribute, names[i]); } } ctxInfo.Finish(this); return(ctxInfo); }
// http://www.w3.org/TR/xslt#literal-result-element private XslNode LoadLiteralResultElement(bool asStylesheet) { Debug.Assert(input.NodeType == XPathNodeType.Element); string prefix = input.Prefix; string name = input.LocalName; string nsUri = input.NamespaceUri; string version = null; string extPrefixes = null; string exclPrefixes = null; string useAttrSets = null; string versionQName = null; List<XslNode> content = new List<XslNode>(); ContextInfo ctxInfo = new ContextInfo(input); /* Process literal attributes */ while (input.MoveToNextAttOrNs()) { if (input.NodeType == XPathNodeType.Namespace) { ctxInfo.AddNamespace(input); } else { Debug.Assert(input.NodeType == XPathNodeType.Attribute); ctxInfo.AddAttribute(input); if (input.IsXsltNamespace()) { if (input.LocalName == input.Atoms.Version) { version = input.Value; versionQName = input.QualifiedName; } else if (input.LocalName == input.Atoms.ExtensionElementPrefixes) { extPrefixes = input.Value; } else if (input.LocalName == input.Atoms.ExcludeResultPrefixes) { exclPrefixes = input.Value; } else if (input.LocalName == input.Atoms.UseAttributeSets) { useAttrSets = input.Value; } else { // just ignore it } } else { XslNode att = f.LiteralAttribute(f.QName(input.LocalName, input.NamespaceUri, input.Prefix), input.Value, input.XslVersion); // QilGenerator takes care of AVTs, and needs line info AddInstruction(content, SetLineInfo(att, ctxInfo.lineInfo)); } } } ctxInfo.Finish(input); if (version != null) { // Enable forwards-compatible behavior if version attribute is not "1.0" input.SetVersion(version, versionQName); } else { if (asStylesheet) { if (Ref.Equal(nsUri, input.Atoms.UriWdXsl) && Ref.Equal(name, input.Atoms.Stylesheet)) { ReportError(/*[XT_025]*/Res.Xslt_WdXslNamespace); } else { ReportError(/*[XT0150]*/Res.Xslt_WrongStylesheetElement); } input.SkipNode(); return null; } } // Parse xsl:extension-element-prefixes attribute (now that forwards-compatible mode is known) InsertExNamespaces(extPrefixes, ref ctxInfo.nsList, /*extensions:*/true); XslNode result; // Now we can determine whether this element is an extension element (spec section 14.1) if (input.IsExtensionNamespace(nsUri)) { // This is not a literal result element, so drop all attributes we have collected content = LoadFallbacks(name); result = f.List(); } else { // Parse xsl:exclude-result-prefixes attribute (now that it's known this is a literal result element) InsertExNamespaces(exclPrefixes, ref ctxInfo.nsList, /*extensions:*/false); // Insert all attribute sets at the beginning of content content.InsertRange(0, ParseUseAttributeSets(useAttrSets, ctxInfo.lineInfo)); content = LoadEndTag(LoadInstructions(content)); result = f.LiteralElement(f.QName(name, nsUri, prefix)); } return SetInfo(result, content, ctxInfo); }
public ContextInfo GetAttributes(int required, int number, string[] names, string[] values) { Debug.Assert(reader.NodeType == XmlNodeType.Element); for (int i = 0; i < number; i ++) { values[i] = null; } string elementName = QualifiedName; ContextInfo ctxInfo = new ContextInfo(this); compiler.EnterForwardsCompatible(); while (MoveToNextAttOrNs()) { if (nodeType == XPathNodeType.Namespace) { ctxInfo.AddNamespace(this); continue; } Debug.Assert(nodeType == XPathNodeType.Attribute); ctxInfo.AddAttribute(this); bool found = false; for (int i = 0; i < number; i ++) { if (IsXsltAttribute(names[i])) { found = true; values[i] = Value; // There are only two XSL elements, xsl:stylesheet/xsl:transform and xsl:output, capable // of having 'version' attribute. And only for the first one this attribute is required. if (Ref.Equal(names[i], Atoms.Version) && i < required) { SetVersion(Value, Atoms.Version); } break; } } if (!found) { // An element from the XSLT namespace may have any attribute not from the XSLT namespace, // provided that the expanded-name of the attribute has a non-null namespace URI. // For example, it may be 'xml:space'. if (IsNullNamespace() || IsXsltNamespace()) { ReportError(/*[XT0090]*/Res.Xslt_InvalidAttribute, QualifiedName, elementName); } } } // Ignore invalid attributes if forwards-compatible behavior is enabled. Note that invalid // attributes may encounter before ForwardCompatibility flag is set to true. For example, // <xsl:stylesheet unknown="foo" version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/> compiler.ExitForwardsCompatible(ForwardCompatibility); // Report missing mandatory attributes for (int i = 0; i < required; i ++) { if (values[i] == null) { ReportError(/*[XT_001]*/Res.Xslt_MissingAttribute, names[i]); } } ctxInfo.Finish(this); return ctxInfo; }