Files
tm_back/pkg/xmlparser/utils.go
T
n.nakhostin 7dc695752b Remove github.com/google/uuid dependency and update module files
- Deleted the `github.com/google/uuid` dependency from `go.mod` to streamline the project and reduce unnecessary dependencies.
- Updated `go.sum` to reflect the removal of the UUID package.
- Enhanced the overall module management by ensuring only necessary dependencies are included.
2025-08-12 12:15:14 +03:30

159 lines
4.0 KiB
Go

package xmlparser
import (
"fmt"
"strings"
)
// ValidationError represents a validation error with details
type ValidationError struct {
Field string `json:"field"`
Message string `json:"message"`
Value string `json:"value,omitempty"`
}
func (ve ValidationError) Error() string {
if ve.Value != "" {
return fmt.Sprintf("validation error in field '%s': %s (value: %s)", ve.Field, ve.Message, ve.Value)
}
return fmt.Sprintf("validation error in field '%s': %s", ve.Field, ve.Message)
}
// ValidationErrors represents multiple validation errors
type ValidationErrors []ValidationError
func (ve ValidationErrors) Error() string {
if len(ve) == 0 {
return "no validation errors"
}
var messages []string
for _, err := range ve {
messages = append(messages, err.Error())
}
return fmt.Sprintf("validation failed with %d error(s): %s", len(ve), strings.Join(messages, "; "))
}
// IsEmpty returns true if there are no validation errors
func (ve ValidationErrors) IsEmpty() bool {
return len(ve) == 0
}
// Add adds a validation error
func (ve *ValidationErrors) Add(field, message, value string) {
*ve = append(*ve, ValidationError{
Field: field,
Message: message,
Value: value,
})
}
// XMLParseError represents an XML parsing error with context
type XMLParseError struct {
Line int `json:"line,omitempty"`
Column int `json:"column,omitempty"`
Element string `json:"element,omitempty"`
Message string `json:"message"`
Original error `json:"-"`
}
func (xpe XMLParseError) Error() string {
var parts []string
if xpe.Element != "" {
parts = append(parts, fmt.Sprintf("element '%s'", xpe.Element))
}
if xpe.Line > 0 {
if xpe.Column > 0 {
parts = append(parts, fmt.Sprintf("line %d, column %d", xpe.Line, xpe.Column))
} else {
parts = append(parts, fmt.Sprintf("line %d", xpe.Line))
}
}
context := ""
if len(parts) > 0 {
context = " (" + strings.Join(parts, ", ") + ")"
}
return fmt.Sprintf("XML parse error%s: %s", context, xpe.Message)
}
// Unwrap returns the original error
func (xpe XMLParseError) Unwrap() error {
return xpe.Original
}
// SanitizeXMLString removes invalid XML characters and cleans the string
func SanitizeXMLString(s string) string {
// Remove control characters except tab, newline, and carriage return
var result strings.Builder
for _, r := range s {
if (r >= 0x20 && r <= 0xD7FF) ||
(r >= 0xE000 && r <= 0xFFFD) ||
(r >= 0x10000 && r <= 0x10FFFF) ||
r == 0x09 || r == 0x0A || r == 0x0D {
result.WriteRune(r)
}
}
return result.String()
}
// ValidateXMLName checks if a string is a valid XML name
func ValidateXMLName(name string) bool {
if name == "" {
return false
}
// XML names must start with a letter or underscore
first := []rune(name)[0]
if !((first >= 'A' && first <= 'Z') ||
(first >= 'a' && first <= 'z') ||
first == '_') {
return false
}
// Subsequent characters can be letters, digits, hyphens, periods, or underscores
for _, r := range []rune(name)[1:] {
if !((r >= 'A' && r <= 'Z') ||
(r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') ||
r == '-' || r == '.' || r == '_') {
return false
}
}
return true
}
// IsValidNamespace checks if a string is a valid XML namespace URI
func IsValidNamespace(namespace string) bool {
if namespace == "" {
return true // Empty namespace is valid
}
// Basic URI validation - should start with http:// or https:// or urn:
return strings.HasPrefix(namespace, "http://") ||
strings.HasPrefix(namespace, "https://") ||
strings.HasPrefix(namespace, "urn:")
}
// NormalizeWhitespace normalizes whitespace in XML text content
func NormalizeWhitespace(s string) string {
// Replace all whitespace sequences with single spaces
fields := strings.Fields(s)
return strings.Join(fields, " ")
}
// TruncateString truncates a string to maxLength and adds "..." if needed
func TruncateString(s string, maxLength int) string {
if len(s) <= maxLength {
return s
}
if maxLength <= 3 {
return s[:maxLength]
}
return s[:maxLength-3] + "..."
}