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  }