Skip to content

Commit 61e77c7

Browse files
committed
Namespace lookup should be based on declarations in scope
1 parent 3c9bec4 commit 61e77c7

File tree

4 files changed

+38
-7
lines changed

4 files changed

+38
-7
lines changed

xslt/context.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,34 @@ func (context *ExecutionContext) EvalXPath(xmlNode xml.Node, data interface{}) (
6868
//TODO: walk up tree to get all namespaces in scope
6969
// libxml probably already makes this info available
7070
func (context *ExecutionContext) RegisterXPathNamespaces(node xml.Node) (err error) {
71-
for _, decl := range node.DeclaredNamespaces() {
72-
context.XPathContext.RegisterNamespace(decl.Prefix, decl.Uri)
71+
seen := make(map[string]bool)
72+
for n := node; n != nil; n = n.Parent() {
73+
for _, decl := range n.DeclaredNamespaces() {
74+
alreadySeen, _ := seen[decl.Prefix]
75+
if !alreadySeen {
76+
context.XPathContext.RegisterNamespace(decl.Prefix, decl.Uri)
77+
seen[decl.Prefix] = true
78+
}
79+
}
7380
}
7481
return
7582
}
7683

7784
// Attempt to map a prefix to a URI.
78-
func (context *ExecutionContext) LookupNamespace(prefix string) (uri string) {
85+
func (context *ExecutionContext) LookupNamespace(prefix string, node xml.Node) (uri string) {
86+
//if given a context node, see if the prefix is in scope
87+
if node != nil {
88+
for n := node; n != nil; n = n.Parent() {
89+
for _, decl := range n.DeclaredNamespaces() {
90+
if decl.Prefix == prefix {
91+
return decl.Uri
92+
}
93+
}
94+
}
95+
return
96+
}
97+
98+
//if no context node, simply check the stylesheet map
7999
for href, pre := range context.Style.NamespaceMapping {
80100
if pre == prefix {
81101
return href

xslt/match.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,13 @@ func (m *CompiledMatch) EvalMatch(node xml.Node, mode string, context *Execution
390390
return false
391391
}
392392
case OP_NS:
393-
uri := context.LookupNamespace(step.Value)
393+
uri := ""
394+
// m.Template.Node
395+
if m.Template != nil {
396+
uri = context.LookupNamespace(step.Value, m.Template.Node)
397+
} else {
398+
uri = context.LookupNamespace(step.Value, nil)
399+
}
394400
if uri != cur.Namespace() {
395401
return false
396402
}

xslt/stylesheet.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ func (style *Stylesheet) ParseTemplate(node xml.Node) {
596596
}
597597

598598
// TODO: validate the name (duplicate should raise error)
599-
template := &Template{Match: match, Mode: mode, Name: name, Priority: p}
599+
template := &Template{Match: match, Mode: mode, Name: name, Priority: p, Node: node}
600600

601601
template.CompileContent(node)
602602

xslt/template.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type Template struct {
1919
Match string
2020
Priority float64
2121
Children []CompiledStep
22+
Node xml.Node
2223
}
2324

2425
type XsltInstruction struct {
@@ -145,9 +146,13 @@ func (i *XsltInstruction) Apply(node xml.Node, context *ExecutionContext) {
145146
context.XPathContext.SetContextPosition(oldpos, oldtotal)
146147
return
147148
}
149+
context.RegisterXPathNamespaces(i.Node)
148150
e := xpath.Compile(scope)
149151
// TODO: ensure we apply strip-space if required
150-
nodes, _ := context.EvalXPathAsNodeset(node, e)
152+
nodes, err := context.EvalXPathAsNodeset(node, e)
153+
if err != nil {
154+
fmt.Println("apply-templates @select", err)
155+
}
151156
if i.sorting != nil {
152157
i.Sort(nodes, context)
153158
}
@@ -260,7 +265,7 @@ func (i *XsltInstruction) Apply(node xml.Node, context *ExecutionContext) {
260265

261266
case "value-of":
262267
e := xpath.Compile(i.Node.Attr("select"))
263-
context.RegisterXPathNamespaces(i.Node.MyDocument().Root())
268+
context.RegisterXPathNamespaces(i.Node)
264269
o, _ := context.EvalXPath(node, e)
265270
switch output := o.(type) {
266271
case []xml.Node:

0 commit comments

Comments
 (0)