github.com/avicd/go-utilx@v0.1.0/xmlx/exporter.go (about) 1 package xmlx 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 type Exporter struct { 9 DropComment bool 10 DropEmpty bool 11 DropCDataSection bool 12 DropProcessingInstruction bool 13 DropDocumentType bool 14 DropDirective bool 15 IncludeSelf bool 16 node *Node 17 } 18 19 func (et *Exporter) ApplyOn(node *Node) string { 20 var exporter *Exporter 21 if et == nil { 22 exporter = &Exporter{node: node, IncludeSelf: true} 23 } else { 24 exporter = &Exporter{ 25 node: node, 26 DropComment: et.DropComment, 27 DropEmpty: et.DropEmpty, 28 DropCDataSection: et.DropCDataSection, 29 DropProcessingInstruction: et.DropProcessingInstruction, 30 DropDocumentType: et.DropDocumentType, 31 DropDirective: et.DropDirective, 32 IncludeSelf: et.IncludeSelf, 33 } 34 } 35 return exporter.export(node) 36 } 37 38 func (et *Exporter) stringifyAttrs(attrs []*Node) string { 39 buffer := &strings.Builder{} 40 for _, attr := range attrs { 41 buffer.WriteString(fmt.Sprintf(" %s=\"%s\"", attr.NameWithPrefix(), attr.Value)) 42 } 43 return buffer.String() 44 } 45 46 func (et *Exporter) export(node *Node) string { 47 buffer := &strings.Builder{} 48 switch node.Type { 49 case ElementNode, DocumentNode: 50 withSelf := node.Type != DocumentNode && (et.IncludeSelf || et.node != node) 51 var selfName string 52 if withSelf { 53 selfName = node.NameWithPrefix() 54 attrsStr := et.stringifyAttrs(node.Attrs) 55 buffer.WriteString(fmt.Sprintf("<%s%s>", selfName, attrsStr)) 56 } 57 for _, p := range node.ChildNodes { 58 buffer.WriteString(et.export(p)) 59 } 60 if withSelf { 61 buffer.WriteString(fmt.Sprintf("</%s>", selfName)) 62 } 63 case TextNode: 64 text := node.Value 65 if et.DropEmpty { 66 text = strings.TrimSpace(node.Value) 67 } 68 buffer.WriteString(text) 69 case CDataSectionNode: 70 if !et.DropCDataSection { 71 buffer.WriteString(fmt.Sprintf("<![CDATA[%s]]>", node.Value)) 72 } 73 case ProcessingInstructionNode: 74 if !et.DropProcessingInstruction { 75 buffer.WriteString(fmt.Sprintf("<?%s%s?>", node.Name, et.stringifyAttrs(node.Attrs))) 76 } 77 case CommentNode: 78 if !et.DropComment { 79 buffer.WriteString(fmt.Sprintf("<!--%s-->", et.node.Value)) 80 } 81 case DocumentTypeNode: 82 if !et.DropDocumentType { 83 buffer.WriteString(fmt.Sprintf("<!DOCTYPE %s%s>", node.Name, node.Value)) 84 } 85 case DirectiveNode: 86 if !et.DropDirective { 87 buffer.WriteString(fmt.Sprintf("<!%s %s>", node.Name, node.Value)) 88 } 89 } 90 return buffer.String() 91 }