use xmltree::{Element, EmitterConfig}; use crate::UpnpObjectType; pub trait UpnpXml { fn to_xml_element(&self) -> Element; fn to_xml(&self) -> String { let elem = self.to_xml_element(); // Configurer l'indentation let config = EmitterConfig::new() .perform_indent(true) .indent_string(" "); // 2 espaces // Sérialiser dans un buffer let mut buf = Vec::new(); // écrire l'élément elem.write_with_config(&mut buf, config) .expect("Failed to write XML"); // Préfixer avec l'en-tête XML let mut xml_string = "\n".to_string(); xml_string.push_str(&String::from_utf8(buf).expect("Invalid UTF-8")); xml_string } fn to_markdown(&self) -> String { let elem = self.to_xml_element(); let mut md = String::new(); fn is_url(s: &str) -> bool { s.starts_with("http://") || s.starts_with("https://") || s.starts_with("urn:") } fn is_image_url(s: &str) -> bool { let s = s.to_lowercase(); s.ends_with(".png") || s.ends_with(".jpg") || s.ends_with(".jpeg") || s.ends_with(".gif") || s.ends_with(".svg") || s.ends_with(".webp") } fn format_value(v: &str) -> String { let v = v.trim().to_string(); // <-- clone du texte nettoyé if is_url(&v) { if is_image_url(&v) { format!("[{}]({})
![]({})", v, v, v) } else { format!("[{}]({})", v, v) } } else { format!("`{}`", v) } } fn recurse(elem: &xmltree::Element, md: &mut String, depth: usize) { let indent = " ".repeat(depth); md.push_str(&format!("{}- **{}**", indent, elem.name)); // Attributs if !elem.attributes.is_empty() { let attrs: Vec = elem .attributes .iter() .map(|(k, v)| format!("{}={}", k, format_value(v))) .collect(); md.push_str(&format!(" ({})", attrs.join(", "))); } // Texte (utilise get_text() maintenant) if let Some(text) = elem.get_text().map(|s| s.trim().to_string()).filter(|s| !s.is_empty()) { md.push_str(&format!(": {}", format_value(&text))); } md.push('\n'); // Enfants for child in &elem.children { if let xmltree::XMLNode::Element(child_elem) = child { recurse(child_elem, md, depth + 1); } } } md.push_str("# UPnP XML (Markdown view)\n\n"); recurse(&elem, &mut md, 0); md } } pub trait UpnpObject: UpnpXml { fn as_upnp_object_type(&self) -> &UpnpObjectType; fn get_name(&self) -> &String { return &self.as_upnp_object_type().name; } fn get_object_type(&self) -> &String { &self.as_upnp_object_type().object_type } }