add paragraph parser to lib, add test for teg
Some checks failed
CI/CD Pipeline / test (push) Failing after 32s
Some checks failed
CI/CD Pipeline / test (push) Failing after 32s
This commit is contained in:
403
src/law/mod.rs
403
src/law/mod.rs
@ -1,5 +1,4 @@
|
||||
use log::{debug, info};
|
||||
use risp::risparser::overview::parse;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@ -8,23 +7,18 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::par;
|
||||
|
||||
use self::responsible::{
|
||||
contains, contains_at_start, contains_without_unter, starts_with_letter, starts_with_number,
|
||||
starts_with_roman_number, starts_with_uppercaseletter,
|
||||
};
|
||||
|
||||
mod responsible;
|
||||
pub mod responsible;
|
||||
|
||||
/// That's our struct, holding all the information of the law text.
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub(crate) struct Law {
|
||||
name: String, //ABGB, UrhG
|
||||
header: Vec<Heading>,
|
||||
pub struct Law {
|
||||
pub name: String, //ABGB, UrhG
|
||||
pub header: Vec<Heading>,
|
||||
}
|
||||
|
||||
impl Law {
|
||||
pub(crate) fn to_md(&self) {
|
||||
//TODO: add test
|
||||
pub fn to_md(&self) {
|
||||
println!("# {}", self.name);
|
||||
|
||||
for header in &self.header {
|
||||
@ -69,10 +63,10 @@ impl From<LawBuilder> for Law {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
struct Heading {
|
||||
name: String, //1. Hauptstück; 3. Theil; ...
|
||||
desc: Option<String>,
|
||||
content: HeadingContent, // 1. Theil; 1. Subtheil; ...
|
||||
pub struct Heading {
|
||||
pub name: String, //1. Hauptstück; 3. Theil; ...
|
||||
pub desc: Option<String>,
|
||||
pub content: HeadingContent, // 1. Theil; 1. Subtheil; ...
|
||||
}
|
||||
|
||||
impl Display for Heading {
|
||||
@ -86,7 +80,7 @@ impl Display for Heading {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
enum HeadingContent {
|
||||
pub enum HeadingContent {
|
||||
Paragraph(Vec<Section>),
|
||||
Heading(Vec<Heading>),
|
||||
}
|
||||
@ -112,23 +106,23 @@ impl From<ClassifierInstance> for HeadingContent {
|
||||
|
||||
/// Is used to generate a law struct. It's organized mainly by classifier.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct LawBuilder {
|
||||
pub struct LawBuilder {
|
||||
/// Name of the law
|
||||
pub(crate) name: String, //ABGB, UrhG
|
||||
name: String, //ABGB, UrhG
|
||||
|
||||
/// Structure of the law text
|
||||
pub(crate) classifiers: Vec<Classifier>,
|
||||
classifiers: Vec<Classifier>,
|
||||
|
||||
/// Instances
|
||||
pub(crate) header: Vec<Rc<RefCell<ClassifierInstance>>>,
|
||||
header: Vec<Rc<RefCell<ClassifierInstance>>>,
|
||||
|
||||
last_instance: Option<Rc<RefCell<ClassifierInstance>>>,
|
||||
|
||||
/// Stores the header of the next paragraph
|
||||
pub(crate) next_para_header: Option<String>,
|
||||
next_para_header: Option<String>,
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) history: Vec<String>,
|
||||
pub history: Vec<String>,
|
||||
}
|
||||
|
||||
impl PartialEq for LawBuilder {
|
||||
@ -141,115 +135,56 @@ impl PartialEq for LawBuilder {
|
||||
}
|
||||
|
||||
impl LawBuilder {
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test(name: &str) -> Self {
|
||||
let mut classifiers = Vec::new();
|
||||
//#[cfg(test)]
|
||||
//pub fn test(name: &str) -> Self {
|
||||
// let mut classifiers = Vec::new();
|
||||
|
||||
if name == "new" {
|
||||
classifiers.push(Classifier::new("a", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("b", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("c", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("d", Arc::new(&contains)));
|
||||
} else if name == "UrhG" {
|
||||
classifiers.push(Classifier::new("Hauptstück", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("Number", Arc::new(&starts_with_number)));
|
||||
}
|
||||
// if name == "new" {
|
||||
// classifiers.push(Classifier::new("a", Arc::new(&contains)).root());
|
||||
// classifiers.push(Classifier::new("b", Arc::new(&contains)));
|
||||
// classifiers.push(Classifier::new("c", Arc::new(&contains)));
|
||||
// classifiers.push(Classifier::new("d", Arc::new(&contains)));
|
||||
// } else if name == "UrhG" {
|
||||
// classifiers.push(Classifier::new("Hauptstück", Arc::new(&contains)).root());
|
||||
// classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)));
|
||||
// classifiers.push(Classifier::new("Number", Arc::new(&starts_with_number)));
|
||||
// }
|
||||
|
||||
Self {
|
||||
name: name.into(),
|
||||
classifiers,
|
||||
header: Vec::new(),
|
||||
next_para_header: None,
|
||||
last_instance: None,
|
||||
#[cfg(test)]
|
||||
history: Vec::new(),
|
||||
}
|
||||
}
|
||||
// Self {
|
||||
// name: name.into(),
|
||||
// classifiers,
|
||||
// header: Vec::new(),
|
||||
// next_para_header: None,
|
||||
// last_instance: None,
|
||||
// #[cfg(test)]
|
||||
// history: Vec::new(),
|
||||
// }
|
||||
//}
|
||||
|
||||
/// Creates a new law builder. Adds classifier for known law texts.
|
||||
pub(crate) fn new(name: &str) -> Self {
|
||||
let mut classifiers = Vec::new();
|
||||
|
||||
let mut law_id = None;
|
||||
if name == "UrhG" {
|
||||
law_id = Some(10_001_848);
|
||||
|
||||
classifiers.push(Classifier::new("Hauptstück", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("Number", Arc::new(&starts_with_number)));
|
||||
} else if name == "MSchG" {
|
||||
law_id = Some(10_002_180);
|
||||
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("Number", Arc::new(&starts_with_number)));
|
||||
} else if name == "ABGB" {
|
||||
law_id = Some(10_001_622);
|
||||
|
||||
classifiers.push(Classifier::new("Einleitung", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("Theil", Arc::new(&contains)).root());
|
||||
|
||||
classifiers.push(Classifier::new("Hauptstück", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("Abtheilung", Arc::new(&contains)));
|
||||
|
||||
classifiers.push(Classifier::new("heading", Arc::new(&contains_at_start)));
|
||||
classifiers.push(Classifier::new("letter", Arc::new(&starts_with_letter)));
|
||||
classifiers.push(Classifier::new("num", Arc::new(&starts_with_number)));
|
||||
classifiers.push(Classifier::new("rom", Arc::new(&starts_with_roman_number)));
|
||||
} else if name == "FSG" {
|
||||
law_id = Some(10_003_898);
|
||||
|
||||
classifiers.push(Classifier::new("Artikel", Arc::new(&contains)).root());
|
||||
|
||||
classifiers.push(Classifier::new(
|
||||
"Abschnitt",
|
||||
Arc::new(&contains_without_unter),
|
||||
));
|
||||
classifiers.push(Classifier::new("Hauptstück", Arc::new(&contains)));
|
||||
classifiers.push(Classifier::new("Unterabschnitt", Arc::new(&contains)));
|
||||
|
||||
classifiers.push(Classifier::new(
|
||||
"uppercase letter",
|
||||
Arc::new(&starts_with_uppercaseletter),
|
||||
));
|
||||
classifiers.push(Classifier::new("num", Arc::new(&starts_with_number)));
|
||||
} else if name == "VVG" {
|
||||
law_id = Some(20_004_425);
|
||||
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)).root());
|
||||
} else if name == "KSchG" {
|
||||
law_id = Some(10_002_462);
|
||||
|
||||
classifiers.push(Classifier::new("Hauptstück", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)));
|
||||
} else if name == "StGB" {
|
||||
law_id = Some(10_002_296);
|
||||
|
||||
classifiers.push(Classifier::new("Teil", Arc::new(&contains)).root());
|
||||
classifiers.push(Classifier::new("Abschnitt", Arc::new(&contains)));
|
||||
}
|
||||
|
||||
let mut builder = Self {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
classifiers,
|
||||
classifiers: Vec::new(),
|
||||
header: Vec::new(),
|
||||
next_para_header: None,
|
||||
last_instance: None,
|
||||
#[cfg(test)]
|
||||
history: Vec::new(),
|
||||
};
|
||||
|
||||
let paragraphs = parse(law_id.unwrap()).unwrap();
|
||||
|
||||
for paragraph in tqdm::tqdm(paragraphs.into_iter()) {
|
||||
let cont = par::parse(¶graph, &mut builder).unwrap();
|
||||
if !cont {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
builder
|
||||
//let paragraphs = overview::parse(law_id.unwrap()).unwrap();
|
||||
|
||||
//for paragraph in tqdm::tqdm(paragraphs.into_iter()) {
|
||||
// let cont = paragraph::parse(¶graph, &mut builder).unwrap();
|
||||
// if !cont {
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
pub fn add_classifier(&mut self, classifier: Classifier) {
|
||||
self.classifiers.push(classifier);
|
||||
}
|
||||
|
||||
fn responsible_classifier(&self, name: &str) -> Option<&Classifier> {
|
||||
@ -279,7 +214,7 @@ impl LawBuilder {
|
||||
}
|
||||
|
||||
/// Sets a new header.
|
||||
pub(crate) fn new_header(&mut self, name: &str) {
|
||||
pub fn new_header(&mut self, name: &str) {
|
||||
let name = name.trim();
|
||||
#[cfg(test)]
|
||||
self.history.push(format!("New_header: {name}"));
|
||||
@ -324,7 +259,7 @@ impl LawBuilder {
|
||||
}
|
||||
|
||||
/// Sets a new description for the last classifier.
|
||||
pub(crate) fn new_desc(&mut self, desc: &str) {
|
||||
pub fn new_desc(&mut self, desc: &str) {
|
||||
let desc = desc.trim();
|
||||
#[cfg(test)]
|
||||
self.history.push(format!("New desc: {desc}"));
|
||||
@ -338,7 +273,7 @@ impl LawBuilder {
|
||||
}
|
||||
|
||||
/// Adds a new paragraph.
|
||||
pub(crate) fn new_par(&mut self, par: String, content: Content) {
|
||||
pub fn new_par(&mut self, par: String, content: Content) {
|
||||
#[cfg(test)]
|
||||
self.history.push(format!(
|
||||
"New_par: {par};{}",
|
||||
@ -362,7 +297,7 @@ impl LawBuilder {
|
||||
}
|
||||
|
||||
/// Next paragraph has a header, store its name.
|
||||
pub(crate) fn new_next_para_header(&mut self, header: &str) {
|
||||
pub fn new_next_para_header(&mut self, header: &str) {
|
||||
#[cfg(test)]
|
||||
self.history.push(format!("New_new_para_header: {header}"));
|
||||
|
||||
@ -376,10 +311,10 @@ impl LawBuilder {
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub(crate) struct Section {
|
||||
pub(crate) symb: String, // §"1", §"2", ...
|
||||
pub(crate) par_header: Option<String>,
|
||||
pub(crate) content: Content,
|
||||
pub struct Section {
|
||||
pub symb: String, // §"1", §"2", ...
|
||||
pub par_header: Option<String>,
|
||||
pub content: Content,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Section {
|
||||
@ -400,12 +335,12 @@ impl fmt::Display for Section {
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub(crate) struct ClassifierInstance {
|
||||
pub(crate) name: String, //e.g. 1 Theilstück
|
||||
pub(crate) desc: Option<String>,
|
||||
pub(crate) sections: Vec<Section>,
|
||||
pub(crate) children: Vec<Rc<RefCell<ClassifierInstance>>>,
|
||||
pub(crate) parent: Option<Rc<RefCell<ClassifierInstance>>>,
|
||||
struct ClassifierInstance {
|
||||
name: String, //e.g. 1 Theilstück
|
||||
desc: Option<String>,
|
||||
sections: Vec<Section>,
|
||||
children: Vec<Rc<RefCell<ClassifierInstance>>>,
|
||||
parent: Option<Rc<RefCell<ClassifierInstance>>>,
|
||||
}
|
||||
|
||||
impl ClassifierInstance {
|
||||
@ -460,12 +395,12 @@ impl From<&str> for ClassifierInstance {
|
||||
type ClassifierApplicable = Arc<dyn Fn(&str, &str) -> bool>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Classifier {
|
||||
pub(crate) name: String, // Hauptstück, Theil, Abschnitt, ol
|
||||
pub struct Classifier {
|
||||
pub name: String, // Hauptstück, Theil, Abschnitt, ol
|
||||
pub(crate) used_for_fn: ClassifierApplicable,
|
||||
pub(crate) instances: Vec<ClassifierInstance>,
|
||||
pub(crate) child: Vec<Rc<RefCell<Classifier>>>,
|
||||
pub(crate) root: bool,
|
||||
instances: Vec<ClassifierInstance>,
|
||||
pub child: Vec<Rc<RefCell<Classifier>>>,
|
||||
pub root: bool,
|
||||
}
|
||||
|
||||
impl PartialEq for Classifier {
|
||||
@ -475,7 +410,7 @@ impl PartialEq for Classifier {
|
||||
}
|
||||
|
||||
impl Classifier {
|
||||
fn new(name: &str, used_for_fn: ClassifierApplicable) -> Self {
|
||||
pub fn new(name: &str, used_for_fn: ClassifierApplicable) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
used_for_fn,
|
||||
@ -485,7 +420,7 @@ impl Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
fn root(self) -> Self {
|
||||
pub fn root(self) -> Self {
|
||||
Self { root: true, ..self }
|
||||
}
|
||||
|
||||
@ -505,7 +440,7 @@ impl std::fmt::Debug for Classifier {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub(crate) enum Content {
|
||||
pub enum Content {
|
||||
Text(String), //This is my direct law text
|
||||
Item(Vec<Content>), //(1) This is general law. (2) This is more specific law
|
||||
List(Vec<Content>),
|
||||
@ -526,94 +461,94 @@ impl Display for Content {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{self, BufRead, Read},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<Vec<String>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let file = File::open(filename)?;
|
||||
let buf_reader = io::BufReader::new(file);
|
||||
buf_reader.lines().collect()
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn test_with_live_data() {
|
||||
let law: Law = LawBuilder::new("UrhG").into();
|
||||
|
||||
let path = Path::new("./data/urhg/builder.result");
|
||||
let mut file = File::open(path).unwrap();
|
||||
let mut json = String::new();
|
||||
file.read_to_string(&mut json).unwrap();
|
||||
|
||||
let expected: Law = serde_json::from_str(&json).unwrap();
|
||||
|
||||
assert_eq!(law, expected);
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn test_stgb_with_live_data() {
|
||||
let law: Law = LawBuilder::new("StGB").into();
|
||||
|
||||
let path = Path::new("./data/stgb/builder.result");
|
||||
let mut file = File::open(path).unwrap();
|
||||
let mut json = String::new();
|
||||
file.read_to_string(&mut json).unwrap();
|
||||
|
||||
let expected: Law = serde_json::from_str(&json).unwrap();
|
||||
|
||||
//println!("{}", serde_json::to_string(&law).unwrap());
|
||||
|
||||
assert_eq!(law, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_builder_full_urhg() {
|
||||
let mut builder = LawBuilder::test("UrhG");
|
||||
|
||||
let path = Path::new("./data/urhg/par");
|
||||
let input = read_lines(path.join("../par.result")).unwrap();
|
||||
|
||||
for i in input {
|
||||
let (command, content) = i.split_once(":").unwrap();
|
||||
|
||||
match command {
|
||||
"New_header" => builder.new_header(content),
|
||||
"New desc" => builder.new_desc(content),
|
||||
"New_new_para_header" => builder.new_next_para_header(content),
|
||||
"New_par" => {
|
||||
let (par, real_content) = i.split_once(";").unwrap();
|
||||
let (_, real_par) = par.split_once(":").unwrap();
|
||||
let real_content: Content = serde_json::from_str(real_content).unwrap();
|
||||
builder.new_par(real_par.trim().into(), real_content);
|
||||
}
|
||||
_ => {
|
||||
panic!("Don't know command '{command}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let actual: Law = builder.into();
|
||||
|
||||
//println!("{}", serde_json::to_string(&law).unwrap());
|
||||
|
||||
let mut file = File::open(path.join("../builder.result")).unwrap();
|
||||
let mut json = String::new();
|
||||
file.read_to_string(&mut json).unwrap();
|
||||
|
||||
let expected = serde_json::from_str(&json).unwrap();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
//#[cfg(test)]
|
||||
//mod tests {
|
||||
// use pretty_assertions::assert_eq;
|
||||
// use std::{
|
||||
// fs::File,
|
||||
// io::{self, BufRead, Read},
|
||||
// path::Path,
|
||||
// };
|
||||
//
|
||||
// use super::*;
|
||||
//
|
||||
// fn read_lines<P>(filename: P) -> io::Result<Vec<String>>
|
||||
// where
|
||||
// P: AsRef<Path>,
|
||||
// {
|
||||
// let file = File::open(filename)?;
|
||||
// let buf_reader = io::BufReader::new(file);
|
||||
// buf_reader.lines().collect()
|
||||
// }
|
||||
//
|
||||
// #[ignore]
|
||||
// #[test]
|
||||
// fn test_with_live_data() {
|
||||
// let law: Law = LawBuilder::new("UrhG").into();
|
||||
//
|
||||
// let path = Path::new("./data/urhg/builder.result");
|
||||
// let mut file = File::open(path).unwrap();
|
||||
// let mut json = String::new();
|
||||
// file.read_to_string(&mut json).unwrap();
|
||||
//
|
||||
// let expected: Law = serde_json::from_str(&json).unwrap();
|
||||
//
|
||||
// assert_eq!(law, expected);
|
||||
// }
|
||||
//
|
||||
// #[ignore]
|
||||
// #[test]
|
||||
// fn test_stgb_with_live_data() {
|
||||
// let law: Law = LawBuilder::new("StGB").into();
|
||||
//
|
||||
// let path = Path::new("./data/stgb/builder.result");
|
||||
// let mut file = File::open(path).unwrap();
|
||||
// let mut json = String::new();
|
||||
// file.read_to_string(&mut json).unwrap();
|
||||
//
|
||||
// let expected: Law = serde_json::from_str(&json).unwrap();
|
||||
//
|
||||
// //println!("{}", serde_json::to_string(&law).unwrap());
|
||||
//
|
||||
// assert_eq!(law, expected);
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_builder_full_urhg() {
|
||||
// let mut builder = LawBuilder::test("UrhG");
|
||||
//
|
||||
// let path = Path::new("./data/urhg/par");
|
||||
// let input = read_lines(path.join("../par.result")).unwrap();
|
||||
//
|
||||
// for i in input {
|
||||
// let (command, content) = i.split_once(":").unwrap();
|
||||
//
|
||||
// match command {
|
||||
// "New_header" => builder.new_header(content),
|
||||
// "New desc" => builder.new_desc(content),
|
||||
// "New_new_para_header" => builder.new_next_para_header(content),
|
||||
// "New_par" => {
|
||||
// let (par, real_content) = i.split_once(";").unwrap();
|
||||
// let (_, real_par) = par.split_once(":").unwrap();
|
||||
// let real_content: Content = serde_json::from_str(real_content).unwrap();
|
||||
// builder.new_par(real_par.trim().into(), real_content);
|
||||
// }
|
||||
// _ => {
|
||||
// panic!("Don't know command '{command}'");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let actual: Law = builder.into();
|
||||
//
|
||||
// //println!("{}", serde_json::to_string(&law).unwrap());
|
||||
//
|
||||
// let mut file = File::open(path.join("../builder.result")).unwrap();
|
||||
// let mut json = String::new();
|
||||
// file.read_to_string(&mut json).unwrap();
|
||||
//
|
||||
// let expected = serde_json::from_str(&json).unwrap();
|
||||
//
|
||||
// assert_eq!(actual, expected);
|
||||
// }
|
||||
//}
|
||||
|
@ -1,17 +1,17 @@
|
||||
pub(crate) fn contains_without_unter(classifier_name: &str, instance_name: &str) -> bool {
|
||||
pub fn contains_without_unter(classifier_name: &str, instance_name: &str) -> bool {
|
||||
instance_name
|
||||
.to_lowercase()
|
||||
.contains(&classifier_name.to_lowercase())
|
||||
&& !instance_name.to_lowercase().contains("unter")
|
||||
}
|
||||
|
||||
pub(crate) fn contains(classifier_name: &str, instance_name: &str) -> bool {
|
||||
pub fn contains(classifier_name: &str, instance_name: &str) -> bool {
|
||||
instance_name
|
||||
.to_lowercase()
|
||||
.contains(&classifier_name.to_lowercase())
|
||||
}
|
||||
|
||||
pub(crate) fn starts_with_roman_number(_: &str, s: &str) -> bool {
|
||||
pub fn starts_with_roman_number(_: &str, s: &str) -> bool {
|
||||
// Define the prefixes for Roman numerals.
|
||||
let roman_prefixes = [
|
||||
"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV",
|
||||
@ -24,20 +24,20 @@ pub(crate) fn starts_with_roman_number(_: &str, s: &str) -> bool {
|
||||
.any(|&prefix| s.starts_with(&(prefix.to_string() + ".")))
|
||||
}
|
||||
|
||||
pub(crate) fn contains_at_start(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
pub fn contains_at_start(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
!instance_name.is_empty() && instance_name.starts_with('@')
|
||||
}
|
||||
|
||||
pub(crate) fn starts_with_number(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
pub fn starts_with_number(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
matches!(instance_name.trim().as_bytes().first(), Some(c) if c.is_ascii_digit())
|
||||
}
|
||||
|
||||
pub(crate) fn starts_with_letter(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
pub fn starts_with_letter(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
instance_name.starts_with(|c: char| c.is_ascii_lowercase())
|
||||
&& (instance_name.chars().nth(1) == Some('.') || instance_name.chars().nth(1) == Some(')'))
|
||||
}
|
||||
|
||||
pub(crate) fn starts_with_uppercaseletter(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
pub fn starts_with_uppercaseletter(_classifier_name: &str, instance_name: &str) -> bool {
|
||||
instance_name.starts_with(|c: char| c.is_ascii_uppercase())
|
||||
&& (instance_name.chars().nth(1) == Some('.') || instance_name.chars().nth(1) == Some(')'))
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod law;
|
||||
pub mod misc;
|
||||
pub mod risparser;
|
||||
|
@ -1,7 +1,4 @@
|
||||
use law::{Law, LawBuilder};
|
||||
|
||||
mod law;
|
||||
mod par;
|
||||
use risp::law::{Law, LawBuilder};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
200
src/par/mod.rs
200
src/par/mod.rs
@ -1,200 +0,0 @@
|
||||
mod parser;
|
||||
|
||||
use crate::{law::LawBuilder, par::parser::Risdok};
|
||||
use log::{debug, info};
|
||||
use risp::misc::Error;
|
||||
|
||||
fn fetch_page(url: &str) -> Result<String, Error> {
|
||||
Ok(ureq::get(url).call()?.into_string()?)
|
||||
}
|
||||
|
||||
pub(crate) fn parse(url: &str, builder: &mut LawBuilder) -> Result<bool, Error> {
|
||||
info!("Parsing {url}");
|
||||
let xml = fetch_page(url)?;
|
||||
parse_from_str(&xml, builder)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_from_str(xml: &str, builder: &mut LawBuilder) -> Result<bool, Error> {
|
||||
let xml = xml.replace("<gdash />", "-"); // used e.g. in §11 Abs. 3 UrhG
|
||||
|
||||
let xml = xml.replace(
|
||||
// in § 17 (2)
|
||||
r#"<liste><schlussteil ebene="0" art="normal" ct="text">(2) Einer Rundfunksendung steht es gleich, wenn ein Werk von einer im In- oder im Ausland gelegenen Stelle aus der Öffentlichkeit im Inland, ähnlich wie durch Rundfunk, aber mit Hilfe von Leitungen wahrnehmbar gemacht wird.</schlussteil></liste>"#,
|
||||
r#"<absatz typ="abs" ct="text" halign="j">(2) Einer Rundfunksendung steht es gleich, wenn ein Werk von einer im In- oder im Ausland gelegenen Stelle aus der Öffentlichkeit im Inland, ähnlich wie durch Rundfunk, aber mit Hilfe von Leitungen wahrnehmbar gemacht wird.</absatz>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
// in § 17 (2)
|
||||
r#"<absatz typ="abs" ct="text" halign="j">(3) Die Verjährungsfrist beträgt</absatz><absatz typ="erltext" ct="text" halign="j">zwanzig Jahre,</absatz><liste><schluss typ="e1" ct="text">wenn die Handlung zwar nicht mit lebenslanger Freiheitsstrafe, aber mit mehr als zehnjähriger Freiheitsstrafe bedroht ist;</schluss></liste><absatz typ="erltext" ct="text" halign="j">zehn Jahre,</absatz><liste><schluss typ="e1" ct="text">wenn die Handlung mit mehr als fünfjähriger, aber höchstens zehnjähriger Freiheitsstrafe bedroht ist;</schluss></liste><absatz typ="erltext" ct="text" halign="j">fünf Jahre,</absatz><liste><schluss typ="e1" ct="text">wenn die Handlung mit mehr als einjähriger, aber höchstens fünfjähriger Freiheitsstrafe bedroht ist;</schluss></liste><absatz typ="erltext" ct="text" halign="j">drei Jahre,</absatz><liste><schluss typ="e1" ct="text">wenn die Handlung mit mehr als sechsmonatiger, aber höchstens einjähriger Freiheitsstrafe bedroht ist;</schluss></liste><absatz typ="erltext" ct="text" halign="j">ein Jahr,</absatz><liste><schluss typ="e1" ct="text">wenn die Handlung mit nicht mehr als sechsmonatiger Freiheitsstrafe oder nur mit Geldstrafe bedroht ist.</schluss></liste>"#,
|
||||
r#"<absatz typ="abs" ct="text" halign="j">(3) Die Verjährungsfrist beträgt zwanzig Jahre, wenn die Handlung zwar nicht mit lebenslanger Freiheitsstrafe, aber mit mehr als zehnjähriger Freiheitsstrafe bedroht ist; zehn Jahre, wenn die Handlung mit mehr als fünfjähriger, aber höchstens zehnjähriger Freiheitsstrafe bedroht ist; fünf Jahre, wenn die Handlung mit mehr als einjähriger, aber höchstens fünfjähriger Freiheitsstrafe bedroht ist; drei Jahre, wenn die Handlung mit mehr als sechsmonatiger, aber höchstens einjähriger Freiheitsstrafe bedroht ist; ein Jahr, wenn die Handlung mit nicht mehr als sechsmonatiger Freiheitsstrafe oder nur mit Geldstrafe bedroht ist.</absatz>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<absatz typ="abs" ct="text" halign="j">(3) Die Frist beträgt</absatz><absatz typ="erltext" ct="text" halign="j">fünfzehn Jahre,</absatz><liste><schlussteil ebene="0.5" art="normal" ct="text">wenn auf Freiheitsstrafe von mehr als einem Jahr, aber nicht mehr als zehn Jahren erkannt worden ist;</schlussteil></liste><absatz typ="erltext" ct="text" halign="j">zehn Jahre,</absatz><liste><schlussteil ebene="0.5" art="normal" ct="text">wenn auf Freiheitsstrafe von mehr als drei Monaten, aber nicht mehr als einem Jahr oder auf eine Geldstrafe unter Festsetzung einer Ersatzfreiheitsstrafe von mehr als drei Monaten erkannt worden ist;</schlussteil></liste><absatz typ="erltext" ct="text" halign="j">fünf Jahre</absatz><liste><schlussteil ebene="0.5" art="normal" ct="text">in allen übrigen Fällen.</schlussteil></liste>"#,
|
||||
r#"<absatz typ="abs" ct="text" halign="j">(3) Die Frist beträgt fünfzehn Jahre, wenn auf Freiheitsstrafe von mehr als einem Jahr, aber nicht mehr als zehn Jahren erkannt worden ist; zehn Jahre, wenn auf Freiheitsstrafe von mehr als drei Monaten, aber nicht mehr als einem Jahr oder auf eine Geldstrafe unter Festsetzung einer Ersatzfreiheitsstrafe von mehr als drei Monaten erkannt worden ist; fünf Jahre in allen übrigen Fällen.</absatz>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g2" ct="text" halign="c">Erster Abschnitt</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Erster Abschnitt</ueberschrift>"#,
|
||||
); // StGB
|
||||
|
||||
let xml = xml.replace(r#"<abstand ct="text" halign="l" />"#, r""); // StGB...
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1min" ct="text" halign="c">Strafbare Handlungen gegen Leib und Leben</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g2" ct="text" halign="c">Strafbare Handlungen gegen Leib und Leben</ueberschrift>"#,
|
||||
); // StGB
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1min" ct="text" halign="c">Allgemeine Bestimmungen</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g2" ct="text" halign="c">Allgemeine Bestimmungen</ueberschrift>"#,
|
||||
); // StGB
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="para" ct="text" halign="c">1. Verwertungsrechte.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">1. Verwertungsrechte.</ueberschrift>"#,
|
||||
); // 1. Verwertungsrechte. before § 14
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Medizinische Behandlung</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="art" ct="text" halign="c">Medizinische Behandlung</ueberschrift>"#,
|
||||
); // 1. Verwertungsrechte. before § 14
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="para" ct="text" halign="c">4b. Presseveröffentlichungen.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">4b. Presseveröffentlichungen.</ueberschrift>"#,
|
||||
); // § 99d UrhG, Titel kein Para.... //TODO: not working
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="para" ct="text" halign="c">Erfordernisse zur Ersitzung:</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="art" ct="text" halign="c">Erfordernisse zur Ersitzung:</ueberschrift>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="art" ct="text" halign="c">"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">@"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Zweyter Theil</ueberschrift><ueberschrift typ="g1" ct="text" halign="c">des</ueberschrift><ueberschrift typ="g1" ct="text" halign="c">bürgerlichen Gesetzbuches.</ueberschrift><ueberschrift typ="g1" ct="text" halign="c">Von dem Sachenrechte.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Zweyter Theil des bürgerlichen Gesetzbuches. Von dem Sachenrechte.</ueberschrift>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Dritter Theil</ueberschrift><ueberschrift typ="g1min" ct="text" halign="c">des</ueberschrift><ueberschrift typ="g1min" ct="text" halign="c">bürgerlichen Gesetzbuches.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Dritter Theil des bürgerlichen Gesetzbuches.</ueberschrift>"#,
|
||||
);
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Von den gemeinschaftlichen Bestimmungen der Personen- und Sachenrechte.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g2" ct="text" halign="c">Von den gemeinschaftlichen Bestimmungen der Personen- und Sachenrechte.</ueberschrift>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Erste Abtheilung</ueberschrift><ueberschrift typ="g2" ct="text" halign="c">des Sachenrechtes.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">Erste Abtheilung des Sachenrechtes.</ueberschrift>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g1min" ct="text" halign="c">Von den dinglichen Rechten.</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g2" ct="text" halign="c">Von den dinglichen Rechten.</ueberschrift>"#,
|
||||
);
|
||||
|
||||
let xml = xml.replace("<super>", ""); // e.g. § 23a in MSchG
|
||||
let xml = xml.replace("</super>", ""); // e.g. § 23a in MSchG
|
||||
let xml = xml.replace("<i>", ""); // § 69 in MSchG
|
||||
let xml = xml.replace("</i>", "");
|
||||
|
||||
let xml = xml.replace("<n>", ""); // § 49b in FSG
|
||||
let xml = xml.replace("</n>", "");
|
||||
|
||||
let xml = xml.replace("<b>", ""); // § 14 in FSG
|
||||
let xml = xml.replace("</b>", "");
|
||||
|
||||
let xml = xml.replace("<tab />", "");
|
||||
|
||||
let xml = xml.replace(
|
||||
r"(Anm.: § 69 aufgehoben durch Art. 1 Z 12, BGBl. I Nr. 124/2017)",
|
||||
r"<gldsym>§ 69.</gldsym>(Anm.: § 69 aufgehoben durch Art. 1 Z 12, BGBl. I Nr. 124/2017)",
|
||||
);
|
||||
|
||||
// § 49d FSG
|
||||
let xml = xml.replace(
|
||||
r#"</absatz><liste><schlussteil ebene="0" art="normal" ct="text">Die Finanzordnungswidrigkeit wird mit einer Geldstrafe bis zu 50 000 Euro geahndet.</schlussteil></liste>"#,
|
||||
r"Die Finanzordnungswidrigkeit wird mit einer Geldstrafe bis zu 50 000 Euro geahndet.</absatz>",
|
||||
);
|
||||
|
||||
// § 127 FSG
|
||||
let xml = xml.replace(
|
||||
r#"<absatz typ="erltext" ct="text" halign="j">Die Öffentlichkeit ist auszuschließen:</absatz>"#,
|
||||
r#"<absatz typ="abs" ct="text" halign="j">Die Öffentlichkeit ist auszuschließen:</absatz>"#,
|
||||
);
|
||||
|
||||
// § 56 FSG
|
||||
let xml = xml.replace(
|
||||
r#"<ueberschrift typ="g2" ct="text" halign="c">A. Allgemeine Bestimmungen</ueberschrift>"#,
|
||||
r#"<ueberschrift typ="g1" ct="text" halign="c">A. Allgemeine Bestimmungen</ueberschrift>"#,
|
||||
);
|
||||
|
||||
// § 167 FSG
|
||||
let xml = xml.replace(
|
||||
r#"<absatz typ="abs" ct="text" halign="j">(1) Gegen die Versäumung einer Frist oder einer mündlichen Verhandlung ist auf Antrag des Beschuldigten oder der Nebenbeteiligten eines anhängigen oder abgeschlossenen Finanzstrafverfahrens die Wiedereinsetzung in den vorigen Stand zu bewilligen, wenn der Antragsteller durch die Versäumung einen Rechtsnachteil erleidet und glaubhaft macht, daß er durch ein unvorhergesehenes oder unabwendbares Ereignis verhindert war, die Frist einzuhalten oder zur Verhandlung zu erscheinen. Daß dem Beschuldigten oder dem Nebenbeteiligten ein Verschulden an der Versäumung zur Last liegt, hindert die Bewilligung der Wiedereinsetzung nicht, wenn es sich nur um einen minderen Grad des Versehens handelt.</absatz>"#,
|
||||
r#"<absatz typ="abs" ct="text" halign="j"><gldsym>§ 167.</gldsym>(1) Gegen die Versäumung einer Frist oder einer mündlichen Verhandlung ist auf Antrag des Beschuldigten oder der Nebenbeteiligten eines anhängigen oder abgeschlossenen Finanzstrafverfahrens die Wiedereinsetzung in den vorigen Stand zu bewilligen, wenn der Antragsteller durch die Versäumung einen Rechtsnachteil erleidet und glaubhaft macht, daß er durch ein unvorhergesehenes oder unabwendbares Ereignis verhindert war, die Frist einzuhalten oder zur Verhandlung zu erscheinen. Daß dem Beschuldigten oder dem Nebenbeteiligten ein Verschulden an der Versäumung zur Last liegt, hindert die Bewilligung der Wiedereinsetzung nicht, wenn es sich nur um einen minderen Grad des Versehens handelt.</absatz>"#,
|
||||
);
|
||||
|
||||
debug!("{xml}");
|
||||
|
||||
let continue_parsing = Risdok::from_str(&xml, builder)?;
|
||||
|
||||
Ok(continue_parsing)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::{
|
||||
fs::{self, File},
|
||||
io::{self, BufRead, Read},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<Vec<String>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let file = File::open(filename)?;
|
||||
let buf_reader = io::BufReader::new(file);
|
||||
buf_reader.lines().collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_par_full_urhg() {
|
||||
let mut builder = LawBuilder::test("UrhG");
|
||||
|
||||
let path = Path::new("./data/urhg/par");
|
||||
let mut entries: Vec<_> = fs::read_dir(path)
|
||||
.unwrap()
|
||||
.filter_map(|entry| entry.ok())
|
||||
.collect();
|
||||
|
||||
entries.sort_by_key(|entry| entry.file_name());
|
||||
|
||||
for entry in entries {
|
||||
let mut file = File::open(path.join(entry.file_name())).unwrap();
|
||||
let mut json = String::new();
|
||||
file.read_to_string(&mut json).unwrap();
|
||||
|
||||
let cont = parse_from_str(&json, &mut builder).unwrap();
|
||||
if !cont {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let expected = read_lines(path.join("../par.result")).unwrap();
|
||||
|
||||
for (actual, expected) in builder.history.iter().zip(&expected) {
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
//! This deals with accessing RIS data.
|
||||
|
||||
pub mod overview;
|
||||
pub mod paragraphs;
|
||||
pub mod paragraph;
|
||||
|
@ -140,7 +140,7 @@ mod tests {
|
||||
for path in paths {
|
||||
let path = path.unwrap();
|
||||
let file_path = format!("{}", path.path().display());
|
||||
let law_id = format!("{}", path.file_name().into_string().unwrap());
|
||||
let law_id = path.file_name().into_string().unwrap().to_string();
|
||||
let law_id: usize = law_id
|
||||
.parse()
|
||||
.expect("Filename needs to be usize (= law_id in RIS)");
|
||||
|
126
src/risparser/paragraph/mod.rs
Normal file
126
src/risparser/paragraph/mod.rs
Normal file
@ -0,0 +1,126 @@
|
||||
//! Deals with getting all paragraphs for a given law text
|
||||
mod parser;
|
||||
|
||||
use log::info;
|
||||
|
||||
use crate::{law::LawBuilder, misc::Error};
|
||||
|
||||
use self::parser::Risdok;
|
||||
|
||||
pub struct Parser {
|
||||
remove: Vec<String>,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn new() -> Self {
|
||||
Self { remove: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn add_string_to_remove(&mut self, data: &str) {
|
||||
self.remove.push(data.into());
|
||||
}
|
||||
|
||||
/// Parses the content available in `url`. Calls appropriate functions in supplied `LawBuilder`.
|
||||
pub fn parse(&self, url: &str, builder: &mut LawBuilder) -> Result<bool, Error> {
|
||||
info!("Parsing {url}");
|
||||
let xml = fetch(url)?;
|
||||
|
||||
self.parse_from_str(&xml, builder)
|
||||
}
|
||||
|
||||
fn parse_from_str(&self, xml: &str, builder: &mut LawBuilder) -> Result<bool, Error> {
|
||||
let mut xml = String::from(xml);
|
||||
for r in &self.remove {
|
||||
xml = xml.replace(r, "");
|
||||
}
|
||||
|
||||
Risdok::from_str(&xml, builder)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
fn fetch(url: &str) -> Result<String, Error> {
|
||||
Ok(ureq::get(url).call()?.into_string()?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn fetch(url: &str) -> Result<String, Error> {
|
||||
use std::{
|
||||
fs,
|
||||
hash::{DefaultHasher, Hash, Hasher},
|
||||
};
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
url.hash(&mut hasher);
|
||||
let hash = format!("{:x}", hasher.finish());
|
||||
|
||||
let expected_filename = format!("./data/cache/par-{hash}");
|
||||
|
||||
match fs::read_to_string(&expected_filename) {
|
||||
Ok(data) => Ok(data),
|
||||
Err(_) => {
|
||||
info!("Not finding url {url} in the cache, downloading...");
|
||||
let data = ureq::get(url).call()?.into_string()?;
|
||||
fs::write(expected_filename, &data).expect("Unable to write file");
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::{fs, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
law::{responsible::contains, Classifier, LawBuilder},
|
||||
risparser::paragraph::Parser,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn paragraph() {
|
||||
let laws = fs::read_dir("./data/expected/overview/")
|
||||
.expect("No folder with expected overview files");
|
||||
|
||||
for law in laws {
|
||||
let path = law.unwrap();
|
||||
let law_path = format!("{}", path.path().display());
|
||||
let law_id = path.file_name().into_string().unwrap().to_string();
|
||||
|
||||
//TODO: Remove this if once all law texts pass
|
||||
if ["10001905".into()].contains(&law_id) {
|
||||
let expected_path = format!("./data/expected/par/{law_id}");
|
||||
|
||||
let pars = fs::read_to_string(law_path).expect("Could not read file {file_path}.");
|
||||
let pars = pars.trim().split('\n').collect::<Vec<&str>>();
|
||||
|
||||
let mut builder = LawBuilder::new("law");
|
||||
builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains)).root());
|
||||
|
||||
let mut parser = Parser::new();
|
||||
parser.add_string_to_remove(r#"<absatz typ="abs" ct="text" halign="j"><i>(§§ 1, 2, 3, 4,6, § 8 Abs. 1 und 2 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)</i></absatz>"#);
|
||||
parser.add_string_to_remove(r#"<absatz typ="abs" ct="text" halign="j"><i>(§§ 1 bis 11 des Gesetzes über die Verschollenheit, die Todeserklärung und die Feststellung der Todeszeit vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)</i></absatz>"#);
|
||||
parser.add_string_to_remove(r#"<absatz typ="abs" ct="text" halign="j"><i>(§ 56 Abs. 3 des Gesetzes vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)</i></absatz>"#);
|
||||
parser.add_string_to_remove(r#"<absatz typ="abs" ct="text" halign="j"><i>(§ 10 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)</i></absatz>"#);
|
||||
parser.add_string_to_remove(r#"<absatz typ="abs" ct="text" halign="j"><i>(§§ 10a, 10b und 10c des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)</i></absatz>"#);
|
||||
parser.add_string_to_remove("<i>");
|
||||
parser.add_string_to_remove("</i>");
|
||||
for par in pars {
|
||||
let cont = parser.parse(par, &mut builder).unwrap();
|
||||
if !cont {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let actual = builder.history;
|
||||
|
||||
let expected = fs::read_to_string(&expected_path)
|
||||
.expect(&format!("Could not read file {expected_path}."));
|
||||
let expected = expected.trim().split('\n').collect::<Vec<&str>>();
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
use risp::misc::Error;
|
||||
use roxmltree::Node;
|
||||
|
||||
use crate::law::{Content, LawBuilder};
|
||||
use crate::{
|
||||
law::{Content, LawBuilder},
|
||||
misc::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) struct Risdok {}
|
||||
@ -99,6 +101,11 @@ impl Abschnitt {
|
||||
} else if Ueberschrift::test(child, "g1min") {
|
||||
let ueberschrift = Ueberschrift::parse(c.next().unwrap(), "g1min");
|
||||
builder.new_header(&ueberschrift.content);
|
||||
} else if Ueberschrift::test(child, "art") {
|
||||
let ueberschrift = Ueberschrift::parse(c.next().unwrap(), "art");
|
||||
if ueberschrift.content.trim().starts_with("Artikel") {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
@ -1 +0,0 @@
|
||||
//! Deals with getting all paragraphs for a given law text
|
Reference in New Issue
Block a user