Skip to content

Commit

Permalink
Add etreeutils support for iterating and searching of direct children
Browse files Browse the repository at this point in the history
  • Loading branch information
russellhaering committed Apr 30, 2018
1 parent bdff9f2 commit 7e8daf6
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions etreeutils/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,80 @@ func NSFindOneCtx(ctx NSContext, el *etree.Element, namespace, tag string) (*etr
return found, nil
}

// NSIterateChildren iterates the children of an element, invoking the passed
// handler with each direct child of the element, and the context surrounding
// that child.
func NSIterateChildren(ctx NSContext, el *etree.Element, handle NSIterHandler) error {
ctx, err := ctx.SubContext(el)
if err != nil {
return err
}

// Iterate the child elements.
for _, child := range el.ChildElements() {
err = handle(ctx, child)
if err != nil {
return err
}
}

return nil
}

// NSFindIterateChildrenCtx takes an element and its surrounding context, and iterates
// the children of that element searching for an element matching the passed namespace
// and tag. For each such element that is found, handle is invoked with the matched
// element and its own surrounding context.
func NSFindChildrenIterateCtx(ctx NSContext, el *etree.Element, namespace, tag string, handle NSIterHandler) error {
err := NSIterateChildren(ctx, el, func(ctx NSContext, el *etree.Element) error {
_ctx, err := ctx.SubContext(el)
if err != nil {
return err
}

currentNS, err := _ctx.LookupPrefix(el.Space)
if err != nil {
return err
}

// Base case, el is the sought after element.
if currentNS == namespace && el.Tag == tag {
return handle(ctx, el)
}

return nil
})

if err != nil && err != ErrTraversalHalted {
return err
}

return nil
}

// NSFindOneChild behaves identically to NSFindOneChildCtx, but uses
// DefaultNSContext for context.
func NSFindOneChild(el *etree.Element, namespace, tag string) (*etree.Element, error) {
return NSFindOneChildCtx(DefaultNSContext, el, namespace, tag)
}

// NSFindOneCtx conducts a depth-first search for the specified element. If such an
// element is found a reference to it is returned.
func NSFindOneChildCtx(ctx NSContext, el *etree.Element, namespace, tag string) (*etree.Element, error) {
var found *etree.Element

err := NSFindChildrenIterateCtx(ctx, el, namespace, tag, func(ctx NSContext, el *etree.Element) error {
found = el
return ErrTraversalHalted
})

if err != nil && err != ErrTraversalHalted {
return nil, err
}

return found, nil
}

// NSBuildParentContext recurses upward from an element in order to build an NSContext
// for its immediate parent. If the element has no parent DefaultNSContext
// is returned.
Expand Down

0 comments on commit 7e8daf6

Please sign in to comment.