44package encode
55
66import (
7+ "errors"
78 "reflect"
89 "strings"
910
@@ -21,21 +22,18 @@ var linkStructType = reflect.TypeOf(types.Link{})
2122// - val interface : input data type.
2223//
2324// See https://github.com/Jisin/filmigo/xpath for examples and full reference.
24- func Xpath (doc * html.Node , val any ) any {
25- st := reflect .TypeOf (val )
26-
27- // https://stackoverflow.com/questions/63421976
28- // v is the interface{}
29- v := reflect .ValueOf (& val ).Elem ()
30- // Allocate a temporary variable with type of the struct.
31- //
32- // v.Elem() is the vale contained in the interface.
33- tmp := reflect .New (v .Elem ().Type ()).Elem ()
34- // Copy the struct value contained in interface to
35- // the temporary variable.
36- tmp .Set (v .Elem ())
37-
38- for i := 0 ; i < tmp .NumField (); i ++ {
25+ func Xpath (doc * html.Node , target any ) error {
26+ rv := reflect .ValueOf (target )
27+ if rv .Kind () != reflect .Pointer || rv .IsNil () {
28+ return errors .New ("input type is not a pointer" )
29+ }
30+
31+ st := reflect .TypeOf (target ).Elem ()
32+
33+ // Access the struct value within the interface
34+ v := reflect .ValueOf (target ).Elem ()
35+
36+ for i := 0 ; i < v .NumField (); i ++ {
3937 field := st .Field (i )
4038
4139 args := strings .Split (field .Tag .Get ("xpath" ), "|" )
@@ -61,18 +59,17 @@ func Xpath(doc *html.Node, val any) any {
6159 path := args [0 ]
6260
6361 node , err := htmlquery .Query (doc , path )
64- if node == nil || err ! = nil {
62+ if err != nil || node = = nil {
6563 continue
6664 }
6765
6866 fieldType := field .Type
6967
70- // Extra options are passed with a separator | in the xpath struct tag, for ex. src to get the src attr of a node
7168 switch method {
7269 case "attr" :
7370 for _ , a := range node .Attr {
7471 if a .Key == attr {
75- tmp .FieldByName (field .Name ).SetString (a .Val )
72+ v .FieldByName (field .Name ).SetString (a .Val )
7673 break
7774 }
7875 }
@@ -81,20 +78,18 @@ func Xpath(doc *html.Node, val any) any {
8178 // If the field is of type []Link all inner a tags are extracted
8279 // If field type is []string innertex of each li tag is extracted
8380 if fieldType .Kind () == reflect .Slice && fieldType .Elem () == linkStructType {
84- links := getLinks (node )
81+ links := GetXpathLinks (node )
8582 lVal := reflect .Append (reflect .ValueOf (links ))
86- tmp .FieldByName (field .Name ).Set (lVal )
83+ v .FieldByName (field .Name ).Set (lVal )
8784 } else if fieldType .Kind () == reflect .Slice && fieldType .Elem ().Kind () == reflect .String {
8885 list := getTextList (node )
8986 lVal := reflect .Append (reflect .ValueOf (list ))
90- tmp .FieldByName (field .Name ).Set (lVal )
87+ v .FieldByName (field .Name ).Set (lVal )
9188 } else {
92- tmp .FieldByName (field .Name ).SetString (htmlquery .InnerText (node ))
89+ v .FieldByName (field .Name ).SetString (htmlquery .InnerText (node ))
9390 }
9491 }
9592 }
9693
97- v .Set (tmp )
98-
99- return val
94+ return nil
10095}
0 commit comments