예제 #1
0
파일: template.go 프로젝트: jbowtie/ratago
func (e *LiteralResultElement) Compile(node xml.Node) {
	for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
		res := CompileSingleNode(cur)
		if res != nil {
			res.Compile(cur)
			e.Children = append(e.Children, res)
		}
	}
}
예제 #2
0
파일: template.go 프로젝트: jbowtie/ratago
// Compile the variable.
//
// TODO: compile the XPath expression and determine if it is a constant
func (i *Variable) Compile(node xml.Node) {
	i.Name = i.Node.Attr("name")
	for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
		res := CompileSingleNode(cur)
		if res != nil {
			res.Compile(cur)
			i.Children = append(i.Children, res)
		}
	}
}
예제 #3
0
파일: template.go 프로젝트: jbowtie/ratago
func (template *Template) CompileContent(node xml.Node) {
	//parse the content and register the match pattern
	for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
		res := CompileSingleNode(cur)
		if res != nil {
			res.Compile(cur)
			template.AddChild(res)
		}
	}
}
예제 #4
0
파일: context.go 프로젝트: jbowtie/ratago
// ChildrenOf returns the node children, ignoring any whitespace-only text nodes that
// are stripped by strip-space or xml:space
func (context *ExecutionContext) ChildrenOf(node xml.Node) (children []xml.Node) {

	for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
		//don't count stripped nodes
		if context.ShouldStrip(cur) {
			continue
		}
		children = append(children, cur)
	}
	return
}
예제 #5
0
// Compile the instruction.
//
// TODO: we should validate the structure during this step
func (i *XsltInstruction) Compile(node xml.Node) {
	for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
		res := CompileSingleNode(cur)
		if cur.Name() == "sort" && cur.Namespace() == XSLT_NAMESPACE {
			i.sorting = append(i.sorting, compileSortFunction(res.(*XsltInstruction)))
			continue
		}
		if res != nil {
			res.Compile(cur)
			i.Children = append(i.Children, res)
		}
	}
}
예제 #6
0
// Here we iterate through the children; this has been moved to its own function
// to facilitate the implementation of xsl:include (where we want the children to
// be treated as if they were part of the calling stylesheet)
func (style *Stylesheet) parseChildren(root xml.Node, fileuri string) (err error) {
	//iterate through children
	for cur := root.FirstChild(); cur != nil; cur = cur.NextSibling() {
		//skip blank nodes
		if IsBlank(cur) {
			continue
		}

		//skip comment nodes
		if cur.NodeType() == xml.XML_COMMENT_NODE {
			continue
		}

		//handle templates
		if IsXsltName(cur, "template") {
			style.ParseTemplate(cur)
			continue
		}

		if IsXsltName(cur, "variable") {
			style.RegisterGlobalVariable(cur)
			continue
		}

		if IsXsltName(cur, "key") {
			name := cur.Attr("name")
			use := cur.Attr("use")
			match := cur.Attr("match")
			k := &Key{make(map[string]xml.Nodeset), use, match}
			style.Keys[name] = k
			continue
		}

		//TODO: this is cheating. Also note global params can have their
		// value overwritten
		if IsXsltName(cur, "param") {
			style.RegisterGlobalVariable(cur)
			continue
		}

		if IsXsltName(cur, "attribute-set") {
			style.RegisterAttributeSet(cur)
			continue
		}

		if IsXsltName(cur, "include") {
			//check for recursion, multiple includes
			loc := cur.Attr("href")
			base := path.Dir(fileuri)
			loc = path.Join(base, loc)
			_, already := style.includes[loc]
			if already {
				panic("Multiple include detected of " + loc)
			}
			style.includes[loc] = true

			//load the stylesheet
			doc, e := xml.ReadFile(loc, xml.StrictParseOption)
			if e != nil {
				fmt.Println(e)
				err = e
				return
			}
			//_, _ = ParseStylesheet(doc, loc)
			//update the including stylesheet
			e = style.parseChildren(doc.Root(), loc)
			if e != nil {
				fmt.Println(e)
				err = e
				return
			}
			continue
		}

		if IsXsltName(cur, "import") {
			//check for recursion, multiple includes
			loc := cur.Attr("href")
			base := path.Dir(fileuri)
			loc = path.Join(base, loc)
			_, already := style.includes[loc]
			if already {
				panic("Multiple include detected of " + loc)
			}
			style.includes[loc] = true
			//increment import; new style context
			doc, _ := xmlReadFile(loc)
			_import, _ := ParseStylesheet(doc, loc)
			style.Imports.PushFront(_import)
			continue
		}

		if IsXsltName(cur, "output") {
			cdata := cur.Attr("cdata-section-elements")
			if cdata != "" {
				style.CDataElements = strings.Fields(cdata)
			}
			style.OutputMethod = cur.Attr("method")
			omit := cur.Attr("omit-xml-declaration")
			if omit == "yes" {
				style.OmitXmlDeclaration = true
			}
			indent := cur.Attr("indent")
			if indent == "yes" {
				style.IndentOutput = true
			}
			standalone := cur.Attr("standalone")
			if standalone == "yes" {
				style.Standalone = true
			}
			encoding := cur.Attr("encoding")
			if encoding != "" && encoding != "utf-8" {
				//TODO: emit a warning if we do not support the encoding
				// if unsupported, leave blank to output default UTF-8
				style.DesiredEncoding = encoding
			}
			style.doctypeSystem = cur.Attr("doctype-system")
			style.doctypePublic = cur.Attr("doctype-public")
			continue
		}

		if IsXsltName(cur, "strip-space") {
			el := cur.Attr("elements")
			if el != "" {
				style.StripSpace = strings.Fields(el)
			}
			continue
		}

		if IsXsltName(cur, "preserve-space") {
			el := cur.Attr("elements")
			if el != "" {
				style.PreserveSpace = strings.Fields(el)
			}
			continue
		}

		if IsXsltName(cur, "namespace-alias") {
			stylens := cur.Attr("stylesheet-prefix")
			resns := cur.Attr("result-prefix")
			style.NamespaceAlias[stylens] = resns
			continue
		}

		if IsXsltName(cur, "decimal-format") {
			fmt.Println("GLOBAL TODO ", cur.Name())
			continue
		}
	}
	return
}
예제 #7
0
func (i *XsltInstruction) copyToOutput(node xml.Node, context *ExecutionContext, recursive bool) {
	switch node.NodeType() {
	case xml.XML_TEXT_NODE:
		if context.UseCDataSection(context.OutputNode) {
			r := context.Output.CreateCDataNode(node.Content())
			context.OutputNode.AddChild(r)
		} else {
			r := context.Output.CreateTextNode(node.Content())
			context.OutputNode.AddChild(r)
		}
	case xml.XML_ATTRIBUTE_NODE:
		aname := node.Name()
		ahref := node.Namespace()
		val := node.Content()
		if ahref == "" {
			context.OutputNode.SetAttr(aname, val)
		} else {
			context.OutputNode.SetNsAttr(ahref, aname, val)
		}
	case xml.XML_COMMENT_NODE:
		r := context.Output.CreateCommentNode(node.Content())
		context.OutputNode.AddChild(r)
	case xml.XML_PI_NODE:
		name := node.Attr("name")
		r := context.Output.CreatePINode(name, node.Content())
		context.OutputNode.AddChild(r)
	case xml.XML_NAMESPACE_DECL:
		//in theory this should work
		//in practice it's a little complicated due to the fact
		//that namespace declarations don't map to the node type
		//very well
		//will need to revisit
		//context.OutputNode.DeclareNamespace(node.Name(), node.Content())
	case xml.XML_ELEMENT_NODE:
		aname := node.Name()
		r := context.Output.CreateElementNode(aname)
		context.OutputNode.AddChild(r)
		ns := node.Namespace()
		if ns != "" {
			//TODO: search through namespaces in-scope
			prefix, _ := context.Style.NamespaceMapping[ns]
			r.SetNamespace(prefix, ns)
		} else {
			//may need to explicitly reset to empty namespace
			def := context.DefaultNamespace(context.OutputNode)
			if def != "" {
				r.SetNamespace("", "")
			}
		}

		//copy namespace declarations
		for _, decl := range node.DeclaredNamespaces() {
			r.DeclareNamespace(decl.Prefix, decl.Uri)
		}

		old := context.OutputNode
		context.OutputNode = r
		if recursive {
			//copy attributes
			for _, attr := range node.AttributeList() {
				i.copyToOutput(attr, context, recursive)
			}
			for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
				i.copyToOutput(cur, context, recursive)
			}
		}
		context.OutputNode = old
	case xml.XML_DOCUMENT_NODE:
		if recursive {
			for cur := node.FirstChild(); cur != nil; cur = cur.NextSibling() {
				i.copyToOutput(cur, context, recursive)
			}
		}
	}
}