Skip to content

Add XML parser (Nessus/OpenVAS, SOAP, configs) - #43

Merged
copyleftdev merged 1 commit into
mainfrom
feat/xml
May 31, 2026
Merged

copyleftdev merged 1 commit into
mainfrom
feat/xml

Conversation

@copyleftdev

@copyleftdev copyleftdev commented May 31, 2026 •

Copy link
Copy Markdown
Owner

Implements the XML plugin — issue #20.

What

XML is a tree, so XmlParser flattens it to rows by finding the record
element
: the most-repeated group of sibling elements (e.g. <ReportItem> under
a Nessus <ReportHost>, or <vuln> in a report; first group in document order
on a tie). Each becomes a row whose columns are its attributes plus its
leaf child elements (text-only children), type-inferred; a child that has its
own children is not flattened. With no repetition the document is a single record
and the root element becomes one row.

Flattened this way it feeds structural and dist like any other corpus — and
unlocks the XML-based security formats (Nessus/OpenVAS scan reports, SOAP).

Dependency

roxmltree — lightweight, pure-Rust, deterministic read-only DOM (kept in the
text-only build).

Routing

  • Detected by an <?xml declaration (STRONG) or a leading element tag
    (TEXT; < + digit is a syslog priority, not XML).
  • Extensions .xml / .nessus.

Errors

Malformed XML is a clean AxError::Parse.

Gates

  • fmt / clippy -D warnings / full workspace tests green (both feature sets).
  • Mutation gate: 0 surviving mutants on xml.rs (the tie-break and the
    leaf/non-leaf distinction are both pinned by tests).
  • Smoke: a 30-finding scan report routes as xml and an anomalous port is
    flagged (exit 1).

Closes #20

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Added XML format parser with support for .xml and .nessus file extensions
    • Automatic XML detection via declaration or element tag recognition
    • Converts XML hierarchies into flattened table structures
    • Robust error handling for malformed and incomplete XML documents

New XmlParser in ax-normalize. XML is a tree, so we flatten to rows by finding
the record element: the most-repeated group of sibling elements (e.g.
<ReportItem> under a Nessus <ReportHost>, or <vuln> in a report; first group in
document order on a tie). Each becomes a row whose columns are its attributes
plus its leaf child elements (text-only children), type-inferred; a child with
its own children is not flattened. With no repetition the document is a single
record and the root element becomes one row. Flattened this way it feeds
structural and dist like any other corpus.

Uses roxmltree (lightweight, pure-Rust, deterministic read-only DOM). Detected
by an <?xml declaration (STRONG) or a leading element tag (TEXT; <digit is a
syslog priority, not XML); extensions .xml/.nessus. Malformed XML is a clean
Parse error.

Mutation gate: 0 surviving mutants on the new file.

Closes #20

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 31, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds an XML parser to ax-normalize by implementing XmlParser as a FormatParser trait, registering it in the default registry, and updating integration tests. The parser flattens XML documents into tabular form by selecting the largest repeated sibling group as record elements and extracting attributes and leaf-child text as columns.

Changes

XML Parser Implementation

Layer / File(s) Summary
Dependency Addition
crates/ax-normalize/Cargo.toml
Adds roxmltree = "0.21" as a dependency for read-only XML DOM parsing and report scanning.
XmlParser Implementation
crates/ax-normalize/src/parsers/xml.rs
Implements XmlParser struct with FormatParser trait methods: sniffing via XML declaration or element tag heuristic, parsing via record-element selection (largest repeated sibling group), attribute and leaf-child extraction into columns, and null mapping for empty leaves. Includes comprehensive unit tests for record selection, tie-breaking, non-leaf skipping, fallback behavior, error handling, and registry resolution.
Parser Registration and Integration
crates/ax-normalize/src/parsers/mod.rs, crates/ax-normalize/src/parser.rs
Exposes xml module and XmlParser re-export, registers XmlParser in default_registry() after PrometheusParser, and updates default_registry_lists_all_formats test to expect "xml" in the deterministic parser ID list.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • copyleftdev/anomalyx#32: Both PRs modify deterministic parser registration in default_registry() and parsers/mod.rs, with XML added here versus syslog in that PR.
  • copyleftdev/anomalyx#36: Both PRs update default_registry_lists_all_formats test to expect new parser IDs in deterministic order.
  • copyleftdev/anomalyx#29: Both PRs modify parser registration wiring in default_registry() and test expectations to integrate a new format parser.

Poem

🐰 A XML parser hops into the fold,
Records flattened, stories told,
Nessus scans now have their place,
Fluttering through the parser race! 🌳

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: adding an XML parser for specific formats (Nessus/OpenVAS and configs), which accurately reflects the primary objective.
Linked Issues check ✅ Passed All acceptance criteria from issue #20 are met: FormatParser implemented with id/extensions/sniff/parse, registered in default_registry, comprehensive tests included, code is clean per cargo fmt/clippy, and mutation testing achieved zero surviving mutants.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #20: new XML parser implementation, registration in mod.rs, dependency addition, and test updates. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/xml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@copyleftdev
copyleftdev merged commit 7bebc81 into main May 31, 2026
1 of 2 checks passed
@copyleftdev
copyleftdev deleted the feat/xml branch May 31, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an XML parser

1 participant