package xmlcheck import ( "bytes" "encoding/xml" "fmt" "io" "strings" ) func Validate(source []byte) error { decoder := xml.NewDecoder(bytes.NewReader(source)) decoder.CharsetReader = charsetReader decoder.Strict = true depth, roots := 0, 0 for { token, err := decoder.Token() if err == io.EOF { break } if err != nil { return fmt.Errorf("некорректный XML: %w", err) } switch node := token.(type) { case xml.StartElement: if depth == 0 { roots++ if roots > 1 { return fmt.Errorf("найдено более одного корневого XML-элемента") } } depth++ case xml.EndElement: depth-- case xml.CharData: if depth == 0 && strings.TrimSpace(string(node)) != "" { return fmt.Errorf("текст за пределами корневого XML-элемента") } } } if roots != 1 || depth != 0 { return fmt.Errorf("нет единственного завершённого корневого XML-элемента") } return nil }