Skip to content

Missing support for xsd::import / xsd::include #3

@elmeunick9

Description

@elmeunick9

While trying to validate XSD documents from UBL 2.4:
https://docs.oasis-open.org/ubl/cs01-UBL-2.4/UBL-2.4.html

In particular:
https://docs.oasis-open.org/ubl/cs01-UBL-2.4/xml/UBL-BusinessCard-2.2-Example.xml

Example main.rs:

use std::fs;
use std::path::Path;
use xmloxide::Document;
use xmloxide::catalog::Catalog;
use xmloxide::tree::NodeKind;
use xmloxide::validation::xsd::{parse_xsd, validate_xsd};

fn main() {
    // 1. Setup your paths
    let catalog_path = "xsd/ubl/UBL-2.4-catalog.xml";
    let base_dir = Path::new("xsd/ubl/"); // The root where 'maindoc' and 'common' folders live

    // 2. Load the UBL Catalog
    let catalog_content = fs::read_to_string(catalog_path).expect("Could not find catalog file");
    let catalog = Catalog::parse(&catalog_content).expect("Failed to parse catalog");

    // 3. Parse your BusinessCard XML
    let xml_content = fs::read_to_string("UBL-BusinessCard-2.2-Example.xml").expect("Could not find XML file");
    let doc = Document::parse_str(&xml_content).expect("Failed to parse XML");

    // 4. Correctly extract the root namespace from NodeId
    let root_id = doc.root_element().expect("XML has no root element");
    let root_node = doc.node(root_id);
    
    let target_ns = if let NodeKind::Element { ref namespace, .. } = root_node.kind {
        // namespace is an Option<String> in this struct
        namespace.as_deref().unwrap_or("")
    } else {
        ""
    };

    println!("Looking for XSD for namespace: {}", target_ns);

    // 5. Use the Catalog to find the relative path
    // In UBL 2.4, this usually resolves to "maindoc/UBL-BusinessCard-2.4.xsd"
    let xsd_rel_path = catalog.resolve_system(target_ns)
        .or_else(|| catalog.resolve_uri(target_ns)) // Fallback to URI just in case
        .expect("Namespace not found in catalog as systemId or URI");

    // 6. Join paths and validate
    let full_xsd_path = base_dir.join(xsd_rel_path);
    let xsd_content = fs::read_to_string(full_xsd_path).expect("Resolved XSD file not found");
    
    let schema = parse_xsd(&xsd_content).expect("Failed to parse XSD");
    let result = validate_xsd(&doc, &schema);

    if result.is_valid {
        println!("✅ Validation Successful!");
    } else {
        println!("❌ Validation Failed: {:?}", result.errors);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions