From 4a1b9a8a378b258a073ca194fc3fe65241fc6892 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 13:50:51 +0200 Subject: [PATCH 01/11] warning for generic configuration with graphml --- src/importer/graphml.rs | 40 +++++++++++++++++-- ...ml__tests__generic_config_warning.snap.new | 6 +++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new diff --git a/src/importer/graphml.rs b/src/importer/graphml.rs index 655dbf44..4b3d5128 100644 --- a/src/importer/graphml.rs +++ b/src/importer/graphml.rs @@ -281,11 +281,16 @@ impl Importer for GraphMLImporter { &self, path: &Path, step_id: StepID, - _config: GenericImportConfiguration, + config: GenericImportConfiguration, tx: Option, ) -> Result> { let reporter = ProgressReporter::new(tx, step_id, 2)?; + if config != self.default_configuration() { + reporter + .warn("Generic configuration keys are currently ignored for GraphML imports.")?; + } + // TODO: support multiple GraphML and connected binary files // TODO: refactor the graphannis_core create to expose the needed functionality directly @@ -314,11 +319,15 @@ impl Importer for GraphMLImporter { #[cfg(test)] mod tests { - use std::path::Path; + use std::{path::Path, sync::mpsc}; use insta::assert_snapshot; + use itertools::Itertools; - use crate::{importer::graphml::GraphMLImporter, test_util::import_as_graphml_string}; + use crate::{ + importer::{GenericImportConfiguration, Importer, graphml::GraphMLImporter}, + test_util::import_as_graphml_string, + }; #[test] fn single_sentence() { @@ -331,4 +340,29 @@ mod tests { assert_snapshot!(actual); } + + #[test] + fn generic_config_warning() { + let input_path = Path::new("tests/data/import/graphml/single_sentence.graphml"); + let import = GraphMLImporter::default(); + let (tx, rx) = mpsc::channel(); + let import = import.import_corpus( + input_path, + crate::StepID { + module_name: "test_import".to_string(), + path: None, + }, + GenericImportConfiguration::new_with_root_name("custom_root".to_string()), + Some(tx), + ); + assert!(import.is_ok()); + assert_snapshot!( + rx.into_iter() + .map(|m| match m { + crate::workflow::StatusMessage::Warning(w) => w, + _ => "".to_string(), + }) + .join("\n") + ); + } } diff --git a/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new b/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new new file mode 100644 index 00000000..49c8dbc1 --- /dev/null +++ b/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new @@ -0,0 +1,6 @@ +--- +source: src/importer/graphml.rs +assertion_line: 359 +expression: "rx.into_iter().map(|m| match m\n{\n crate::workflow::StatusMessage::Warning(w) => w, _ => \"\".to_string(),\n}).join(\"\\n\")" +--- +Generic configuration keys are currently ignored for GraphML imports. From bb3060264ac82b6ca6dd7415c73b15908918efda Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 13:51:32 +0200 Subject: [PATCH 02/11] fixed snapshot --- ...natto__importer__graphml__tests__generic_config_warning.snap} | 1 - 1 file changed, 1 deletion(-) rename src/importer/snapshots/{annatto__importer__graphml__tests__generic_config_warning.snap.new => annatto__importer__graphml__tests__generic_config_warning.snap} (92%) diff --git a/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new b/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap similarity index 92% rename from src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new rename to src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap index 49c8dbc1..d121a5a4 100644 --- a/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap.new +++ b/src/importer/snapshots/annatto__importer__graphml__tests__generic_config_warning.snap @@ -1,6 +1,5 @@ --- source: src/importer/graphml.rs -assertion_line: 359 expression: "rx.into_iter().map(|m| match m\n{\n crate::workflow::StatusMessage::Warning(w) => w, _ => \"\".to_string(),\n}).join(\"\\n\")" --- Generic configuration keys are currently ignored for GraphML imports. From e2f37932ef621097afb1125ab1c5f6c0eefdae72 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 13:53:10 +0200 Subject: [PATCH 03/11] update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52b98e65..22b0d4be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- import `graphml`: When generic config attributes are used, such as `extensions`, which the importer has to ignore, a warning is displayed + ## [0.51.0] - 2026-04-10 ### Added From 9aabac984c77f4c0813e71b01c3712dd67640b75 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 14:17:13 +0200 Subject: [PATCH 04/11] update snapshots --- ...manipulator__visualize__tests__dot_single_sentence_full.snap | 2 +- ...anipulator__visualize__tests__dot_single_sentence_limit.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_full.snap b/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_full.snap index 29a99d57..88c54c44 100644 --- a/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_full.snap +++ b/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_full.snap @@ -17,8 +17,8 @@ digraph G { 2[shape=box label="single_sentence/zossen#text\n \nannis:node_type=datasource"] 1[shape=box label="single_sentence/zossen\n \nannis:doc=zossen\nannis:node_type=corpus"] 0[shape=box label="single_sentence\n \nannis:node_type=corpus"] - 3[shape=box label="single_sentence/zossen#n1\n \nsyntax:cat=ROOT\nannis:layer=syntax\nannis:node_type=node"] 4[shape=box label="single_sentence/zossen#n2\n \nsyntax:cat=S\nannis:layer=syntax\nannis:node_type=node"] + 3[shape=box label="single_sentence/zossen#n1\n \nsyntax:cat=ROOT\nannis:layer=syntax\nannis:node_type=node"] 5[shape=box label="single_sentence/zossen#n3\n \nsyntax:cat=NP\nannis:layer=syntax\nannis:node_type=node"] 8[shape=box label="single_sentence/zossen#n4\n \nsyntax:cat=PP\nannis:layer=syntax\nannis:node_type=node"] 12[shape=box label="single_sentence/zossen#n5\n \nsyntax:cat=NP\nannis:layer=syntax\nannis:node_type=node"] diff --git a/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_limit.snap b/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_limit.snap index 5288c856..262d431d 100644 --- a/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_limit.snap +++ b/src/manipulator/snapshots/annatto__manipulator__visualize__tests__dot_single_sentence_limit.snap @@ -13,8 +13,8 @@ digraph G { 2[shape=box label="single_sentence/zossen#text\n \nannis:node_type=datasource"] 1[shape=box label="single_sentence/zossen\n \nannis:doc=zossen\nannis:node_type=corpus"] 0[shape=box label="single_sentence\n \nannis:node_type=corpus"] - 3[shape=box label="single_sentence/zossen#n1\n \nsyntax:cat=ROOT\nannis:layer=syntax\nannis:node_type=node"] 4[shape=box label="single_sentence/zossen#n2\n \nsyntax:cat=S\nannis:layer=syntax\nannis:node_type=node"] + 3[shape=box label="single_sentence/zossen#n1\n \nsyntax:cat=ROOT\nannis:layer=syntax\nannis:node_type=node"] 5[shape=box label="single_sentence/zossen#n3\n \nsyntax:cat=NP\nannis:layer=syntax\nannis:node_type=node"] 8[shape=box label="single_sentence/zossen#n4\n \nsyntax:cat=PP\nannis:layer=syntax\nannis:node_type=node"] 3 -> 6 [label="annis/inherited-coverage (C)" color=darkgreen fontcolor=darkgreen style=dotted] From 5539cbd5f2ea5f218a4a4adc49b1d68a1bbbec34 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 14:17:23 +0200 Subject: [PATCH 05/11] update facet and graphannis --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9dbd1ba2..38b808a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,12 +21,12 @@ console = "0.15" csv = "1.3" encoding_rs = "0.8" encoding_rs_io = "0.1.7" -facet = "0.28.0" -facet-reflect = "0.28.0" +facet = "0.46.0" +facet-reflect = "0.46.0" git2 = { version = "0.20.2", default-features = false } glob = "0.3" -graphannis = "4.1.1" -graphannis-core = "4.1.1" +graphannis = "4.1.4" +graphannis-core = "4.1.4" graphviz-rust = "0.9.7" indicatif = "0.17" itertools = "0.12" From d4927921d437b8ff8d846bb914609fc38ada1055 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 14:17:35 +0200 Subject: [PATCH 06/11] adapt to new facet api --- src/util/documentation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/documentation.rs b/src/util/documentation.rs index 975eea24..55e33720 100644 --- a/src/util/documentation.rs +++ b/src/util/documentation.rs @@ -78,7 +78,7 @@ impl From<&Variant> for ModuleInfo { let shape = m.shape(); if let Some(inner) = shape.inner { // This can be a boxed type - inner() + inner } else { shape } From e5e6bec80b59065cfa8c11199e047abd0d113f86 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 14:19:06 +0200 Subject: [PATCH 07/11] update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b0d4be..2ebbd36e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - import `graphml`: When generic config attributes are used, such as `extensions`, which the importer has to ignore, a warning is displayed +### Changed + +- internal library for documentation generation had changed, as it also changed in graphannis + ## [0.51.0] - 2026-04-10 ### Added From 9c6c2700fb0fd342f99d8f9fb8793ac0e7184647 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 16:00:26 +0200 Subject: [PATCH 08/11] always use effective name --- src/bin/annatto.rs | 16 ++++++++-------- src/bin/documentation_generation/mod.rs | 6 +++--- src/util/documentation.rs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/bin/annatto.rs b/src/bin/annatto.rs index e6c28ad5..d03f6f9c 100644 --- a/src/bin/annatto.rs +++ b/src/bin/annatto.rs @@ -244,7 +244,7 @@ fn list_modules() { peek_enum_variants(ReadFrom::SHAPE) .unwrap_or_default() .iter() - .map(|v| v.name.to_lowercase()) + .map(|v| v.effective_name().to_lowercase()) .join(", "), ]; table_builder.push_record(import_row); @@ -254,7 +254,7 @@ fn list_modules() { peek_enum_variants(WriteAs::SHAPE) .unwrap_or_default() .iter() - .map(|v| v.name.to_lowercase()) + .map(|v| v.effective_name().to_lowercase()) .join(", "), ]; table_builder.push_record(export_row); @@ -264,7 +264,7 @@ fn list_modules() { peek_enum_variants(GraphOp::SHAPE) .unwrap_or_default() .iter() - .map(|v| v.name.to_lowercase()) + .map(|v| v.effective_name().to_lowercase()) .join(", "), ]; table_builder.push_record(graph_op_row); @@ -288,18 +288,18 @@ fn module_info(name: &str) { let matching_importers: Vec<_> = peek_enum_variants(ReadFrom::SHAPE) .unwrap_or_default() .iter() - .filter(|m| m.name.to_lowercase() == name.to_lowercase()) + .filter(|m| m.effective_name().to_lowercase() == name.to_lowercase()) .collect(); let matching_exporters: Vec<_> = peek_enum_variants(WriteAs::SHAPE) .unwrap_or_default() .iter() - .filter(|m| m.name.to_lowercase() == name.to_lowercase()) + .filter(|m| m.effective_name().to_lowercase() == name.to_lowercase()) .collect(); let matching_graph_ops: Vec<_> = peek_enum_variants(GraphOp::SHAPE) .unwrap_or_default() .iter() - .filter(|m| m.name.to_lowercase() == name.to_lowercase()) + .filter(|m| m.effective_name().to_lowercase() == name.to_lowercase()) .collect(); if matching_importers.is_empty() @@ -333,7 +333,7 @@ fn module_info(name: &str) { print_markdown("# Graph operations\n\n"); for m in matching_graph_ops { // The name of the module is taken from the wrapper enum - let module_name = m.name.to_lowercase(); + let module_name = m.effective_name().to_lowercase(); // Get the inner type wrapped by the graph operations enum and use // its documentation and fields if let Some(inner_field) = m.data.fields.first().map(|m| m.shape()) @@ -349,7 +349,7 @@ fn module_info(name: &str) { .fields .iter() .map(|f| ModuleConfiguration { - name: f.name.to_lowercase(), + name: f.effective_name().to_lowercase(), description: documentation::clean_string(f.doc), }) .collect(); diff --git a/src/bin/documentation_generation/mod.rs b/src/bin/documentation_generation/mod.rs index f4973205..2bc0fc9c 100644 --- a/src/bin/documentation_generation/mod.rs +++ b/src/bin/documentation_generation/mod.rs @@ -36,7 +36,7 @@ fn write_module_list_table( importers .iter() .map(|m| { - let module_name = m.name.to_lowercase(); + let module_name = m.effective_name().to_lowercase(); let file_stem = module_name.replace("unstable:", ""); format!("[{module_name}](importers/{file_stem}.md)") }) @@ -49,7 +49,7 @@ fn write_module_list_table( exporters .iter() .map(|m| { - let module_name = m.name.to_lowercase(); + let module_name = m.effective_name().to_lowercase(); let file_stem = module_name.replace("unstable:", ""); format!("[{module_name}](exporters/{file_stem}.md)") }) @@ -62,7 +62,7 @@ fn write_module_list_table( graph_ops .iter() .map(|m| { - let module_name = m.name.to_lowercase(); + let module_name = m.effective_name().to_lowercase(); let file_stem = module_name.replace("unstable:", ""); format!("[{module_name}](graph_ops/{file_stem}.md)") }) diff --git a/src/util/documentation.rs b/src/util/documentation.rs index 55e33720..ffcb602b 100644 --- a/src/util/documentation.rs +++ b/src/util/documentation.rs @@ -66,7 +66,7 @@ pub struct ModuleInfo { impl From<&Variant> for ModuleInfo { fn from(module: &Variant) -> Self { // The name of the module is taken from the wrapper enum - let module_name = module.name.to_lowercase(); + let module_name = module.effective_name().to_lowercase(); // Get the inner type wrapped by the graph operations enum and use // its documentation and fields let mut result = Self { @@ -93,7 +93,7 @@ impl From<&Variant> for ModuleInfo { .fields .iter() .map(|f| ModuleConfiguration { - name: f.name.to_lowercase(), + name: f.effective_name().to_lowercase(), description: clean_string(f.doc), }) .collect(); From f8d219b5754f491e99990bf91114609818a93d93 Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 16:06:23 +0200 Subject: [PATCH 09/11] clippy --- src/exporter/table.rs | 2 +- src/importer/graphml.rs | 20 ++++++++------------ src/importer/text/tokenizer.rs | 2 +- src/importer/textgrid.rs | 4 +--- src/importer/toolbox.rs | 5 ++--- src/workflow.rs | 4 +--- 6 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/exporter/table.rs b/src/exporter/table.rs index 43baf89d..e6263564 100644 --- a/src/exporter/table.rs +++ b/src/exporter/table.rs @@ -314,7 +314,7 @@ impl ExportTable { let mut prefixes = sources.iter().map(|_| "in").collect_vec(); prefixes.extend(targets.iter().map(|_| "out")); for ((connected_node_name, component, mut edge_annotations), prefix) in - sources.into_iter().chain(targets.into_iter()).zip(prefixes) + sources.into_iter().chain(targets).zip(prefixes) { let qualified_name = [ prefix, diff --git a/src/importer/graphml.rs b/src/importer/graphml.rs index 4b3d5128..8ddb662f 100644 --- a/src/importer/graphml.rs +++ b/src/importer/graphml.rs @@ -163,18 +163,16 @@ fn read_graphml( level += 1; match e.name().0 { - b"graph" => { - if level == 2 { + b"graph" + if level == 2 => { in_graph = true; } - } - b"key" => { - if level == 2 { + b"key" + if level == 2 => { add_annotation_key(&mut keys, e.attributes())?; } - } - b"node" => { - if in_graph && level == 3 { + b"node" + if in_graph && level == 3 => { // Get the ID of this node for att in e.attributes() { let att = att?; @@ -184,9 +182,8 @@ fn read_graphml( } } } - } - b"edge" => { - if in_graph && level == 3 { + b"edge" + if in_graph && level == 3 => { // Get the source and target node IDs for att in e.attributes() { let att = att?; @@ -202,7 +199,6 @@ fn read_graphml( } } } - } b"data" => { for att in e.attributes() { let att = att?; diff --git a/src/importer/text/tokenizer.rs b/src/importer/text/tokenizer.rs index 279f3373..334567e7 100644 --- a/src/importer/text/tokenizer.rs +++ b/src/importer/text/tokenizer.rs @@ -325,7 +325,7 @@ impl TreeTaggerTokenizer { } } result.push(Token::new_val(current_token)); - result.extend(suffix.into_iter()); + result.extend(suffix); } } } diff --git a/src/importer/textgrid.rs b/src/importer/textgrid.rs index d93e233c..26766da7 100644 --- a/src/importer/textgrid.rs +++ b/src/importer/textgrid.rs @@ -246,8 +246,7 @@ impl DocumentMapper<'_> { } let mut token_ids = Vec::new(); let mut result = BTreeMap::new(); - let mut counter = 1; - for (time_range, token_text) in token_sorted_by_time { + for (counter, (time_range, token_text)) in (1..).zip(token_sorted_by_time.into_iter()) { let id = map_token( u, &NodeInfo::new(&counter.to_string(), &self.doc_path, &self.text_node_name), @@ -261,7 +260,6 @@ impl DocumentMapper<'_> { token_ids.push(id.clone()); result.insert(time_range.0, id.clone()); result.insert(time_range.1, id); - counter += 1; } add_order_relations(u, &token_ids, None)?; diff --git a/src/importer/toolbox.rs b/src/importer/toolbox.rs index 898b0aa3..76466442 100644 --- a/src/importer/toolbox.rs +++ b/src/importer/toolbox.rs @@ -315,11 +315,10 @@ impl ImportToolBox { }; } } - (Rule::spaces, _) => { - if build_joint { + (Rule::spaces, _) + if build_joint => { join_list.push(entry_or_space.as_str()); } - } (Rule::null, false) => { timeline_id += 1; } diff --git a/src/workflow.rs b/src/workflow.rs index 0569e0e1..20ce480c 100644 --- a/src/workflow.rs +++ b/src/workflow.rs @@ -457,8 +457,7 @@ impl Workflow { } // Execute all manipulators in sequence if let Some(ref manipulators) = self.graph_op { - let mut graph_op_position = 1; - for desc in manipulators.iter() { + for (graph_op_position, desc) in (1..).zip(manipulators.iter()) { let step_id = StepID::from_graphop_step(desc, graph_op_position); let workflow_directory = &desc.workflow_directory; desc.execute( @@ -473,7 +472,6 @@ impl Workflow { reason: reason.to_string(), manipulator: step_id.to_string(), })?; - graph_op_position += 1; if let Some(ref tx) = tx { tx.send(crate::workflow::StatusMessage::StepDone { id: step_id })?; From 9a51a252cfde004b0d18098af3cc50909d543adc Mon Sep 17 00:00:00 2001 From: Martin Klotz Date: Tue, 28 Apr 2026 16:06:38 +0200 Subject: [PATCH 10/11] clippy --- src/importer/textgrid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/importer/textgrid.rs b/src/importer/textgrid.rs index 26766da7..9ab2ebfa 100644 --- a/src/importer/textgrid.rs +++ b/src/importer/textgrid.rs @@ -246,7 +246,7 @@ impl DocumentMapper<'_> { } let mut token_ids = Vec::new(); let mut result = BTreeMap::new(); - for (counter, (time_range, token_text)) in (1..).zip(token_sorted_by_time.into_iter()) { + for (counter, (time_range, token_text)) in (1..).zip(token_sorted_by_time) { let id = map_token( u, &NodeInfo::new(&counter.to_string(), &self.doc_path, &self.text_node_name), From 57ce468c7fb5af109808122ef6bfea97777698c1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:07:29 +0000 Subject: [PATCH 11/11] Format Rust code using rustfmt --- src/importer/graphml.rs | 60 +++++++++++++++++++---------------------- src/importer/toolbox.rs | 7 +++-- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/importer/graphml.rs b/src/importer/graphml.rs index 8ddb662f..d6bf1f9b 100644 --- a/src/importer/graphml.rs +++ b/src/importer/graphml.rs @@ -163,42 +163,38 @@ fn read_graphml( level += 1; match e.name().0 { - b"graph" - if level == 2 => { - in_graph = true; - } - b"key" - if level == 2 => { - add_annotation_key(&mut keys, e.attributes())?; - } - b"node" - if in_graph && level == 3 => { - // Get the ID of this node - for att in e.attributes() { - let att = att?; - if att.key.0 == b"id" { - current_node_id = - Some(String::from_utf8_lossy(&att.value).to_string()); - } + b"graph" if level == 2 => { + in_graph = true; + } + b"key" if level == 2 => { + add_annotation_key(&mut keys, e.attributes())?; + } + b"node" if in_graph && level == 3 => { + // Get the ID of this node + for att in e.attributes() { + let att = att?; + if att.key.0 == b"id" { + current_node_id = + Some(String::from_utf8_lossy(&att.value).to_string()); } } - b"edge" - if in_graph && level == 3 => { - // Get the source and target node IDs - for att in e.attributes() { - let att = att?; - if att.key.0 == b"source" { - current_source_id = - Some(String::from_utf8_lossy(&att.value).to_string()); - } else if att.key.0 == b"target" { - current_target_id = - Some(String::from_utf8_lossy(&att.value).to_string()); - } else if att.key.0 == b"label" { - current_component = - Some(String::from_utf8_lossy(&att.value).to_string()); - } + } + b"edge" if in_graph && level == 3 => { + // Get the source and target node IDs + for att in e.attributes() { + let att = att?; + if att.key.0 == b"source" { + current_source_id = + Some(String::from_utf8_lossy(&att.value).to_string()); + } else if att.key.0 == b"target" { + current_target_id = + Some(String::from_utf8_lossy(&att.value).to_string()); + } else if att.key.0 == b"label" { + current_component = + Some(String::from_utf8_lossy(&att.value).to_string()); } } + } b"data" => { for att in e.attributes() { let att = att?; diff --git a/src/importer/toolbox.rs b/src/importer/toolbox.rs index 76466442..3697ef3a 100644 --- a/src/importer/toolbox.rs +++ b/src/importer/toolbox.rs @@ -315,10 +315,9 @@ impl ImportToolBox { }; } } - (Rule::spaces, _) - if build_joint => { - join_list.push(entry_or_space.as_str()); - } + (Rule::spaces, _) if build_joint => { + join_list.push(entry_or_space.as_str()); + } (Rule::null, false) => { timeline_id += 1; }