1use crate::error::{RdfXmlParseError, RdfXmlSyntaxError};
2use crate::utils::*;
3use oxilangtag::LanguageTag;
4use oxiri::{Iri, IriParseError};
5#[cfg(feature = "rdf-12")]
6use oxrdf::BaseDirection;
7use oxrdf::vocab::rdf;
8use oxrdf::{BlankNode, Literal, NamedNode, NamedOrBlankNode, Term, Triple};
9use quick_xml::escape::{resolve_xml_entity, unescape_with};
10use quick_xml::events::attributes::Attribute;
11use quick_xml::events::*;
12use quick_xml::name::{LocalName, Namespace, PrefixDeclaration, PrefixIter, ResolveResult};
13use quick_xml::{Decoder, Error, NsReader, Writer};
14use std::borrow::Cow;
15use std::collections::{HashMap, HashSet};
16use std::io::{BufReader, Read};
17use std::str;
18#[cfg(feature = "async-tokio")]
19use tokio::io::{AsyncRead, BufReader as AsyncBufReader};
20
21#[derive(Default, Clone)]
57#[must_use]
58pub struct RdfXmlParser {
59 lenient: bool,
60 base: Option<Iri<String>>,
61}
62
63impl RdfXmlParser {
64 #[inline]
66 pub fn new() -> Self {
67 Self::default()
68 }
69
70 #[inline]
76 pub fn lenient(mut self) -> Self {
77 self.lenient = true;
78 self
79 }
80
81 #[deprecated(note = "Use `lenient()` instead", since = "0.2.0")]
82 #[inline]
83 pub fn unchecked(self) -> Self {
84 self.lenient()
85 }
86
87 #[inline]
88 pub fn with_base_iri(mut self, base_iri: impl Into<String>) -> Result<Self, IriParseError> {
89 self.base = Some(Iri::parse(base_iri.into())?);
90 Ok(self)
91 }
92
93 pub fn for_reader<R: Read>(self, reader: R) -> ReaderRdfXmlParser<R> {
122 ReaderRdfXmlParser {
123 results: Vec::new(),
124 parser: self.into_internal(BufReader::new(reader)),
125 reader_buffer: Vec::default(),
126 }
127 }
128
129 #[cfg(feature = "async-tokio")]
162 pub fn for_tokio_async_reader<R: AsyncRead + Unpin>(
163 self,
164 reader: R,
165 ) -> TokioAsyncReaderRdfXmlParser<R> {
166 TokioAsyncReaderRdfXmlParser {
167 results: Vec::new(),
168 parser: self.into_internal(AsyncBufReader::new(reader)),
169 reader_buffer: Vec::default(),
170 }
171 }
172
173 pub fn for_slice(self, slice: &(impl AsRef<[u8]> + ?Sized)) -> SliceRdfXmlParser<'_> {
202 SliceRdfXmlParser {
203 results: Vec::new(),
204 parser: self.into_internal(slice.as_ref()),
205 }
206 }
207
208 fn into_internal<T>(self, reader: T) -> InternalRdfXmlParser<T> {
209 let mut reader = NsReader::from_reader(reader);
210 reader.config_mut().expand_empty_elements = true;
211 InternalRdfXmlParser {
212 reader,
213 state: vec![RdfXmlState::Doc {
214 base_iri: self.base.clone(),
215 }],
216 custom_entities: HashMap::new(),
217 in_literal_depth: 0,
218 known_rdf_id: HashSet::default(),
219 is_end: false,
220 lenient: self.lenient,
221 }
222 }
223}
224
225#[must_use]
256pub struct ReaderRdfXmlParser<R: Read> {
257 results: Vec<Triple>,
258 parser: InternalRdfXmlParser<BufReader<R>>,
259 reader_buffer: Vec<u8>,
260}
261
262impl<R: Read> Iterator for ReaderRdfXmlParser<R> {
263 type Item = Result<Triple, RdfXmlParseError>;
264
265 fn next(&mut self) -> Option<Self::Item> {
266 loop {
267 if let Some(triple) = self.results.pop() {
268 return Some(Ok(triple));
269 } else if self.parser.is_end {
270 return None;
271 }
272 if let Err(e) = self.parse_step() {
273 return Some(Err(e));
274 }
275 }
276 }
277}
278
279impl<R: Read> ReaderRdfXmlParser<R> {
280 pub fn prefixes(&self) -> RdfXmlPrefixesIter<'_> {
313 RdfXmlPrefixesIter {
314 inner: self.parser.reader.prefixes(),
315 decoder: self.parser.reader.decoder(),
316 lenient: self.parser.lenient,
317 }
318 }
319
320 pub fn base_iri(&self) -> Option<&str> {
340 Some(self.parser.current_base_iri()?.as_str())
341 }
342
343 pub fn buffer_position(&self) -> u64 {
345 self.parser.reader.buffer_position()
346 }
347
348 fn parse_step(&mut self) -> Result<(), RdfXmlParseError> {
349 self.reader_buffer.clear();
350 let event = self
351 .parser
352 .reader
353 .read_event_into(&mut self.reader_buffer)?;
354 self.parser.parse_event(event, &mut self.results)
355 }
356}
357
358#[cfg(feature = "async-tokio")]
393#[must_use]
394pub struct TokioAsyncReaderRdfXmlParser<R: AsyncRead + Unpin> {
395 results: Vec<Triple>,
396 parser: InternalRdfXmlParser<AsyncBufReader<R>>,
397 reader_buffer: Vec<u8>,
398}
399
400#[cfg(feature = "async-tokio")]
401impl<R: AsyncRead + Unpin> TokioAsyncReaderRdfXmlParser<R> {
402 pub async fn next(&mut self) -> Option<Result<Triple, RdfXmlParseError>> {
404 loop {
405 if let Some(triple) = self.results.pop() {
406 return Some(Ok(triple));
407 } else if self.parser.is_end {
408 return None;
409 }
410 if let Err(e) = self.parse_step().await {
411 return Some(Err(e));
412 }
413 }
414 }
415
416 pub fn prefixes(&self) -> RdfXmlPrefixesIter<'_> {
452 RdfXmlPrefixesIter {
453 inner: self.parser.reader.prefixes(),
454 decoder: self.parser.reader.decoder(),
455 lenient: self.parser.lenient,
456 }
457 }
458
459 pub fn base_iri(&self) -> Option<&str> {
482 Some(self.parser.current_base_iri()?.as_str())
483 }
484
485 pub fn buffer_position(&self) -> u64 {
487 self.parser.reader.buffer_position()
488 }
489
490 async fn parse_step(&mut self) -> Result<(), RdfXmlParseError> {
491 self.reader_buffer.clear();
492 let event = self
493 .parser
494 .reader
495 .read_event_into_async(&mut self.reader_buffer)
496 .await?;
497 self.parser.parse_event(event, &mut self.results)
498 }
499}
500
501#[must_use]
532pub struct SliceRdfXmlParser<'a> {
533 results: Vec<Triple>,
534 parser: InternalRdfXmlParser<&'a [u8]>,
535}
536
537impl Iterator for SliceRdfXmlParser<'_> {
538 type Item = Result<Triple, RdfXmlSyntaxError>;
539
540 fn next(&mut self) -> Option<Self::Item> {
541 loop {
542 if let Some(triple) = self.results.pop() {
543 return Some(Ok(triple));
544 } else if self.parser.is_end {
545 return None;
546 }
547 if let Err(RdfXmlParseError::Syntax(e)) = self.parse_step() {
548 return Some(Err(e));
550 }
551 }
552 }
553}
554
555impl SliceRdfXmlParser<'_> {
556 pub fn prefixes(&self) -> RdfXmlPrefixesIter<'_> {
589 RdfXmlPrefixesIter {
590 inner: self.parser.reader.prefixes(),
591 decoder: self.parser.reader.decoder(),
592 lenient: self.parser.lenient,
593 }
594 }
595
596 pub fn base_iri(&self) -> Option<&str> {
616 Some(self.parser.current_base_iri()?.as_str())
617 }
618
619 pub fn buffer_position(&self) -> u64 {
621 self.parser.reader.buffer_position()
622 }
623
624 fn parse_step(&mut self) -> Result<(), RdfXmlParseError> {
625 let event = self.parser.reader.read_event()?;
626 self.parser.parse_event(event, &mut self.results)
627 }
628}
629
630pub struct RdfXmlPrefixesIter<'a> {
634 inner: PrefixIter<'a>,
635 decoder: Decoder,
636 lenient: bool,
637}
638
639impl<'a> Iterator for RdfXmlPrefixesIter<'a> {
640 type Item = (&'a str, &'a str);
641
642 #[inline]
643 fn next(&mut self) -> Option<Self::Item> {
644 loop {
645 let (key, value) = self.inner.next()?;
646 return Some((
647 match key {
648 PrefixDeclaration::Default => "",
649 PrefixDeclaration::Named(name) => {
650 let Ok(Cow::Borrowed(name)) = self.decoder.decode(name) else {
651 continue;
652 };
653 let Ok(Cow::Borrowed(name)) = unescape_with(name, |_| None) else {
654 continue;
655 };
656 if !self.lenient && !is_nc_name(name) {
657 continue; }
659 name
660 }
661 },
662 {
663 let Ok(Cow::Borrowed(value)) = self.decoder.decode(value.0) else {
664 continue;
665 };
666 let Ok(Cow::Borrowed(value)) = unescape_with(value, |_| None) else {
667 continue;
668 };
669 if !self.lenient && Iri::parse(value).is_err() {
670 continue; }
672 value
673 },
674 ));
675 }
676 }
677
678 #[inline]
679 fn size_hint(&self) -> (usize, Option<usize>) {
680 self.inner.size_hint()
681 }
682}
683
684const RDF_ABOUT: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#about";
685const RDF_ABOUT_EACH: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#aboutEach";
686const RDF_ABOUT_EACH_PREFIX: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#aboutEachPrefix";
687const RDF_BAG_ID: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#bagID";
688const RDF_DATATYPE: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#datatype";
689const RDF_DESCRIPTION: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#Description";
690const RDF_ID: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#ID";
691const RDF_LI: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#li";
692const RDF_NODE_ID: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#nodeID";
693const RDF_PARSE_TYPE: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#parseType";
694const RDF_RDF: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#RDF";
695const RDF_RESOURCE: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#resource";
696const RDF_VERSION: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#version";
697const RDF_ANNOTATION: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#annotation";
698const RDF_ANNOTATION_NODE_ID: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#annotationNodeID";
699
700const RESERVED_RDF_ELEMENTS: [&str; 11] = [
701 RDF_ABOUT,
702 RDF_ABOUT_EACH,
703 RDF_ABOUT_EACH_PREFIX,
704 RDF_BAG_ID,
705 RDF_DATATYPE,
706 RDF_ID,
707 RDF_LI,
708 RDF_NODE_ID,
709 RDF_PARSE_TYPE,
710 RDF_RDF,
711 RDF_RESOURCE,
712];
713
714const RESERVED_RDF_ATTRIBUTES: [&str; 5] = [
715 RDF_ABOUT_EACH,
716 RDF_ABOUT_EACH_PREFIX,
717 RDF_LI,
718 RDF_RDF,
719 RDF_RESOURCE,
720];
721
722#[derive(Clone, Debug)]
723enum NodeOrText {
724 Node(NamedOrBlankNode),
725 Text(String),
726}
727
728enum RdfXmlState {
729 Doc {
730 base_iri: Option<Iri<String>>,
731 },
732 Rdf {
733 base_iri: Option<Iri<String>>,
734 language: Option<String>,
735 #[cfg(feature = "rdf-12")]
736 base_direction: Option<BaseDirection>,
737 #[cfg(feature = "rdf-12")]
738 rdf_version: Option<RdfVersion>,
739 },
740 NodeElt {
741 base_iri: Option<Iri<String>>,
742 language: Option<String>,
743 #[cfg(feature = "rdf-12")]
744 base_direction: Option<BaseDirection>,
745 subject: NamedOrBlankNode,
746 li_counter: u64,
747 #[cfg(feature = "rdf-12")]
748 rdf_version: Option<RdfVersion>,
749 },
750 PropertyElt {
751 iri: NamedNode,
753 base_iri: Option<Iri<String>>,
754 language: Option<String>,
755 #[cfg(feature = "rdf-12")]
756 base_direction: Option<BaseDirection>,
757 subject: NamedOrBlankNode,
758 object: Option<NodeOrText>,
759 id_attr: Option<NamedNode>,
760 #[cfg(feature = "rdf-12")]
761 annotation_attr: Option<NamedNode>,
762 #[cfg(feature = "rdf-12")]
763 annotation_node_id_attr: Option<BlankNode>,
764 datatype_attr: Option<NamedNode>,
765 #[cfg(feature = "rdf-12")]
766 rdf_version: Option<RdfVersion>,
767 },
768 ParseTypeCollectionPropertyElt {
769 iri: NamedNode,
770 base_iri: Option<Iri<String>>,
771 language: Option<String>,
772 #[cfg(feature = "rdf-12")]
773 base_direction: Option<BaseDirection>,
774 subject: NamedOrBlankNode,
775 objects: Vec<NamedOrBlankNode>,
776 id_attr: Option<NamedNode>,
777 #[cfg(feature = "rdf-12")]
778 annotation_attr: Option<NamedNode>,
779 #[cfg(feature = "rdf-12")]
780 annotation_node_id_attr: Option<BlankNode>,
781 #[cfg(feature = "rdf-12")]
782 rdf_version: Option<RdfVersion>,
783 },
784 ParseTypeLiteralPropertyElt {
785 iri: NamedNode,
786 base_iri: Option<Iri<String>>,
787 language: Option<String>,
788 #[cfg(feature = "rdf-12")]
789 base_direction: Option<BaseDirection>,
790 subject: NamedOrBlankNode,
791 writer: Writer<Vec<u8>>,
792 id_attr: Option<NamedNode>,
793 #[cfg(feature = "rdf-12")]
794 annotation_attr: Option<NamedNode>,
795 #[cfg(feature = "rdf-12")]
796 annotation_node_id_attr: Option<BlankNode>,
797 emit: bool, #[cfg(feature = "rdf-12")]
799 rdf_version: Option<RdfVersion>,
800 },
801 #[cfg(feature = "rdf-12")]
802 ParseTypeTriplePropertyElt {
803 iri: NamedNode,
804 base_iri: Option<Iri<String>>,
805 language: Option<String>,
806 base_direction: Option<BaseDirection>,
807 subject: NamedOrBlankNode,
808 id_attr: Option<NamedNode>,
809 annotation_attr: Option<NamedNode>,
810 annotation_node_id_attr: Option<BlankNode>,
811 rdf_version: Option<RdfVersion>,
812 triples: Vec<Triple>,
813 },
814}
815
816struct InternalRdfXmlParser<R> {
817 reader: NsReader<R>,
818 state: Vec<RdfXmlState>,
819 custom_entities: HashMap<String, String>,
820 in_literal_depth: usize,
821 known_rdf_id: HashSet<String>,
822 is_end: bool,
823 lenient: bool,
824}
825
826impl<R> InternalRdfXmlParser<R> {
827 fn parse_event(
828 &mut self,
829 event: Event<'_>,
830 results: &mut Vec<Triple>,
831 ) -> Result<(), RdfXmlParseError> {
832 match event {
833 Event::Start(event) => self.parse_start_event(&event, results),
834 Event::End(event) => self.parse_end_event(&event, results),
835 Event::Empty(_) => Err(RdfXmlSyntaxError::msg(
836 "The expand_empty_elements option must be enabled",
837 )
838 .into()),
839 Event::Text(event) => self.parse_text_event(&event),
840 Event::CData(event) => self.parse_text_event(&event.escape()?),
841 Event::Comment(_) | Event::PI(_) => Ok(()),
842 Event::Decl(decl) => {
843 if let Some(encoding) = decl.encoding() {
844 if !is_utf8(&encoding?) {
845 return Err(RdfXmlSyntaxError::msg(
846 "Only UTF-8 is supported by the RDF/XML parser",
847 )
848 .into());
849 }
850 }
851 Ok(())
852 }
853 Event::DocType(dt) => self.parse_doctype(&dt),
854 Event::Eof => {
855 self.is_end = true;
856 Ok(())
857 }
858 }
859 }
860
861 fn parse_doctype(&mut self, dt: &BytesText<'_>) -> Result<(), RdfXmlParseError> {
862 for input in self
864 .reader
865 .decoder()
866 .decode(dt.as_ref())?
867 .split('<')
868 .skip(1)
869 {
870 if let Some(input) = input.strip_prefix("!ENTITY") {
871 let input = input.trim_start().strip_prefix('%').unwrap_or(input);
872 let (entity_name, input) = input.trim_start().split_once(|c: char| c.is_ascii_whitespace()).ok_or_else(|| {
873 RdfXmlSyntaxError::msg(
874 "<!ENTITY declarations should contain both an entity name and an entity value",
875 )
876 })?;
877 let input = input.trim_start().strip_prefix('\"').ok_or_else(|| {
878 RdfXmlSyntaxError::msg("<!ENTITY values should be enclosed in double quotes")
879 })?;
880 let (entity_value, input) = input.split_once('"').ok_or_else(|| {
881 RdfXmlSyntaxError::msg(
882 "<!ENTITY declarations values should be enclosed in double quotes",
883 )
884 })?;
885 input.trim_start().strip_prefix('>').ok_or_else(|| {
886 RdfXmlSyntaxError::msg("<!ENTITY declarations values should end with >")
887 })?;
888
889 let entity_value =
891 unescape_with(entity_value, |e| self.resolve_entity(e)).map_err(Error::from)?;
892 self.custom_entities
893 .insert(entity_name.to_owned(), entity_value.to_string());
894 }
895 }
896 Ok(())
897 }
898
899 fn parse_start_event(
900 &mut self,
901 event: &BytesStart<'_>,
902 results: &mut Vec<Triple>,
903 ) -> Result<(), RdfXmlParseError> {
904 #[derive(PartialEq, Eq)]
905 enum RdfXmlParseType {
906 Default,
907 Collection,
908 Literal,
909 Resource,
910 #[cfg(feature = "rdf-12")]
911 Triple,
912 Other,
913 }
914
915 #[derive(PartialEq, Eq)]
916 enum RdfXmlNextProduction {
917 Rdf,
918 NodeElt,
919 PropertyElt { subject: NamedOrBlankNode },
920 }
921
922 if let Some(RdfXmlState::ParseTypeLiteralPropertyElt { writer, .. }) = self.state.last_mut()
924 {
925 let mut clean_event = BytesStart::new(
926 self.reader
927 .decoder()
928 .decode(event.name().as_ref())?
929 .to_string(),
930 );
931 for attr in event.attributes() {
932 clean_event.push_attribute(attr.map_err(Error::InvalidAttr)?);
933 }
934 if self.in_literal_depth == 0 {
935 for (prefix, namespace) in self.reader.prefixes() {
936 match prefix {
937 PrefixDeclaration::Default => {
938 clean_event.push_attribute(("xmlns".as_bytes(), namespace.into_inner()))
939 }
940 PrefixDeclaration::Named(name) => {
941 let mut attr = Vec::with_capacity(6 + name.len());
942 attr.extend_from_slice(b"xmlns:");
943 attr.extend_from_slice(name);
944 clean_event.push_attribute((attr.as_slice(), namespace.into_inner()))
945 }
946 }
947 }
948 }
949 writer.write_event(Event::Start(clean_event))?;
950 self.in_literal_depth += 1;
951 return Ok(());
952 }
953
954 let (tag_namespace, tag_local_name) = self.reader.resolve_element(event.name());
955 let tag_name = self.resolve_ns_name(tag_namespace, tag_local_name)?;
956
957 let mut language = None;
959 let mut base_iri = None;
960 let mut id_attr = None;
961 let mut node_id_attr = None;
962 let mut about_attr = None;
963 let mut property_attrs = Vec::default();
964 let mut resource_attr = None;
965 let mut datatype_attr = None;
966 let mut parse_type = RdfXmlParseType::Default;
967 let mut type_attr = None;
968 #[cfg(feature = "rdf-12")]
969 let mut base_direction_attr = None;
970 #[cfg(feature = "rdf-12")]
971 let mut rdf_version = None;
972 #[cfg(feature = "rdf-12")]
973 let mut annotation_attr = None;
974 #[cfg(feature = "rdf-12")]
975 let mut annotation_node_id_attr = None;
976
977 for attribute in event.attributes() {
978 let attribute = attribute.map_err(Error::InvalidAttr)?;
979 let (attribute_namespace, attribute_local_name) =
980 self.reader.resolve_attribute(attribute.key);
981 if attribute_namespace
982 == ResolveResult::Bound(Namespace(b"http://www.w3.org/XML/1998/namespace"))
983 {
984 match attribute.key.local_name().as_ref() {
985 b"lang" => {
986 let tag = self.convert_attribute(&attribute)?.to_ascii_lowercase();
987 language = Some(if self.lenient {
988 tag
989 } else {
990 LanguageTag::parse(tag.clone())
991 .map_err(|error| {
992 RdfXmlSyntaxError::invalid_language_tag(tag, error)
993 })?
994 .into_inner()
995 });
996 }
997 b"base" => {
998 let iri = self.convert_attribute(&attribute)?;
999 base_iri = Some(if self.lenient {
1000 Iri::parse_unchecked(iri.into_owned())
1001 } else {
1002 Iri::parse(iri.clone().into_owned()).map_err(|error| {
1003 RdfXmlSyntaxError::invalid_iri(iri.into(), error)
1004 })?
1005 })
1006 }
1007 _ => (), }
1009 } else if attribute.key.as_ref().starts_with(b"xml") {
1010 } else if cfg!(feature = "rdf-12")
1012 && attribute_namespace
1013 == ResolveResult::Bound(Namespace(b"http://www.w3.org/2005/11/its"))
1014 && attribute.key.local_name().as_ref() == b"dir"
1015 {
1016 #[cfg(feature = "rdf-12")]
1017 {
1018 base_direction_attr = Some(attribute);
1019 }
1020 } else if cfg!(feature = "rdf-12")
1021 && attribute_namespace
1022 == ResolveResult::Bound(Namespace(b"http://www.w3.org/2005/11/its"))
1023 && attribute.key.local_name().as_ref() == b"version"
1024 {
1025 } else {
1027 let attribute_url =
1028 self.resolve_ns_name(attribute_namespace.clone(), attribute_local_name)?;
1029 if *attribute_url == *RDF_ID {
1030 let mut id = self.convert_attribute(&attribute)?.into_owned();
1031 if !is_nc_name(&id) {
1032 return Err(RdfXmlSyntaxError::msg(format!(
1033 "{id} is not a valid rdf:ID value"
1034 ))
1035 .into());
1036 }
1037 id.insert(0, '#');
1038 id_attr = Some(id);
1039 } else if *attribute_url == *RDF_BAG_ID {
1040 let bag_id = self.convert_attribute(&attribute)?;
1041 if !is_nc_name(&bag_id) {
1042 return Err(RdfXmlSyntaxError::msg(format!(
1043 "{bag_id} is not a valid rdf:bagID value"
1044 ))
1045 .into());
1046 }
1047 } else if *attribute_url == *RDF_NODE_ID {
1048 let id = self.convert_attribute(&attribute)?;
1049 if !is_nc_name(&id) {
1050 return Err(RdfXmlSyntaxError::msg(format!(
1051 "{id} is not a valid rdf:nodeID value"
1052 ))
1053 .into());
1054 }
1055 node_id_attr = Some(BlankNode::new_unchecked(id));
1056 } else if *attribute_url == *RDF_ABOUT {
1057 about_attr = Some(attribute);
1058 } else if *attribute_url == *RDF_RESOURCE {
1059 resource_attr = Some(attribute);
1060 } else if *attribute_url == *RDF_DATATYPE {
1061 datatype_attr = Some(attribute);
1062 } else if *attribute_url == *RDF_PARSE_TYPE {
1063 parse_type = match self.convert_attribute(&attribute)?.as_ref() {
1064 "Collection" => RdfXmlParseType::Collection,
1065 "Literal" => RdfXmlParseType::Literal,
1066 "Resource" => RdfXmlParseType::Resource,
1067 #[cfg(feature = "rdf-12")]
1068 "Triple" => RdfXmlParseType::Triple,
1069 _ => RdfXmlParseType::Other,
1070 };
1071 } else if cfg!(feature = "rdf-12") && *attribute_url == *RDF_VERSION {
1072 #[cfg(feature = "rdf-12")]
1073 {
1074 rdf_version =
1075 Some(RdfVersion::from_str(&self.convert_attribute(&attribute)?)?);
1076 }
1077 } else if cfg!(feature = "rdf-12") && *attribute_url == *RDF_ANNOTATION {
1078 #[cfg(feature = "rdf-12")]
1079 {
1080 annotation_attr = Some(attribute);
1081 }
1082 } else if cfg!(feature = "rdf-12") && *attribute_url == *RDF_ANNOTATION_NODE_ID {
1083 #[cfg(feature = "rdf-12")]
1084 {
1085 annotation_node_id_attr = Some(attribute);
1086 }
1087 } else if attribute_url == rdf::TYPE.as_str() {
1088 type_attr = Some(attribute);
1089 } else if RESERVED_RDF_ATTRIBUTES.contains(&&*attribute_url) {
1090 return Err(RdfXmlSyntaxError::msg(format!(
1091 "{attribute_url} is not a valid attribute"
1092 ))
1093 .into());
1094 } else {
1095 property_attrs.push((
1096 self.parse_iri(attribute_url)?,
1097 self.convert_attribute(&attribute)?.into(),
1098 ));
1099 }
1100 }
1101 }
1102
1103 let id_attr = if let Some(iri) = id_attr {
1105 let iri = self.resolve_iri(base_iri.as_ref(), iri.into())?;
1106 if !self.lenient {
1107 if self.known_rdf_id.contains(iri.as_str()) {
1108 return Err(RdfXmlSyntaxError::msg(format!(
1109 "{iri} has already been used as rdf:ID value"
1110 ))
1111 .into());
1112 }
1113 self.known_rdf_id.insert(iri.as_str().into());
1114 }
1115 Some(iri)
1116 } else {
1117 None
1118 };
1119 let about_attr = if let Some(attr) = about_attr {
1120 Some(self.convert_iri_attribute(base_iri.as_ref(), &attr)?)
1121 } else {
1122 None
1123 };
1124 let resource_attr = if let Some(attr) = resource_attr {
1125 Some(self.convert_iri_attribute(base_iri.as_ref(), &attr)?)
1126 } else {
1127 None
1128 };
1129 let datatype_attr = if let Some(attr) = datatype_attr {
1130 Some(self.convert_iri_attribute(base_iri.as_ref(), &attr)?)
1131 } else {
1132 None
1133 };
1134 let type_attr = if let Some(attr) = type_attr {
1135 Some(self.convert_iri_attribute(base_iri.as_ref(), &attr)?)
1136 } else {
1137 None
1138 };
1139 #[cfg(feature = "rdf-12")]
1140 let base_direction = if rdf_version
1141 .unwrap_or_else(|| self.current_rdf_version())
1142 .supports_its_dir()
1143 {
1144 if let Some(attr) = base_direction_attr {
1145 Some(match self.convert_attribute(&attr)?.as_ref() {
1146 "ltr" => BaseDirection::Ltr,
1147 "rtl" => BaseDirection::Rtl,
1148 base => {
1149 return Err(RdfXmlSyntaxError::msg(format!(
1150 "Invalid base direction: '{base}'"
1151 ))
1152 .into());
1153 }
1154 })
1155 } else {
1156 None
1157 }
1158 } else {
1159 None
1160 };
1161 #[cfg(feature = "rdf-12")]
1162 let annotation_attr = if let Some(attr) = annotation_attr {
1163 Some(self.convert_iri_attribute(base_iri.as_ref(), &attr)?)
1164 } else {
1165 None
1166 };
1167 #[cfg(feature = "rdf-12")]
1168 let annotation_node_id_attr = if let Some(attr) = annotation_node_id_attr {
1169 let id = self.convert_attribute(&attr)?;
1170 if !is_nc_name(&id) {
1171 return Err(RdfXmlSyntaxError::msg(format!(
1172 "{id} is not a valid rdf:annotationNodeID value"
1173 ))
1174 .into());
1175 }
1176 Some(BlankNode::new_unchecked(id))
1177 } else {
1178 None
1179 };
1180
1181 let expected_production = match self.state.last() {
1182 Some(RdfXmlState::Doc { .. }) => RdfXmlNextProduction::Rdf,
1183 Some(
1184 RdfXmlState::Rdf { .. }
1185 | RdfXmlState::PropertyElt { .. }
1186 | RdfXmlState::ParseTypeCollectionPropertyElt { .. },
1187 ) => RdfXmlNextProduction::NodeElt,
1188 Some(RdfXmlState::NodeElt { subject, .. }) => RdfXmlNextProduction::PropertyElt {
1189 subject: subject.clone(),
1190 },
1191 Some(RdfXmlState::ParseTypeLiteralPropertyElt { .. }) => {
1192 return Err(
1193 RdfXmlSyntaxError::msg("ParseTypeLiteralPropertyElt production children should never be considered as a RDF/XML content").into()
1194 );
1195 }
1196 #[cfg(feature = "rdf-12")]
1197 Some(RdfXmlState::ParseTypeTriplePropertyElt { .. }) => RdfXmlNextProduction::NodeElt,
1198 None => {
1199 return Err(RdfXmlSyntaxError::msg(
1200 "No state in the stack: the XML is not balanced",
1201 )
1202 .into());
1203 }
1204 };
1205
1206 let new_state = match expected_production {
1207 RdfXmlNextProduction::Rdf => {
1208 if *tag_name == *RDF_RDF {
1209 RdfXmlState::Rdf {
1210 base_iri,
1211 language,
1212 #[cfg(feature = "rdf-12")]
1213 base_direction,
1214 #[cfg(feature = "rdf-12")]
1215 rdf_version,
1216 }
1217 } else if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) {
1218 return Err(RdfXmlSyntaxError::msg(format!(
1219 "Invalid node element tag name: {tag_name}"
1220 ))
1221 .into());
1222 } else {
1223 self.build_node_elt(
1224 self.parse_iri(tag_name)?,
1225 base_iri,
1226 language,
1227 #[cfg(feature = "rdf-12")]
1228 base_direction,
1229 id_attr,
1230 node_id_attr,
1231 about_attr,
1232 type_attr,
1233 property_attrs,
1234 #[cfg(feature = "rdf-12")]
1235 rdf_version,
1236 results,
1237 )?
1238 }
1239 }
1240 RdfXmlNextProduction::NodeElt => {
1241 if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) {
1242 return Err(RdfXmlSyntaxError::msg(format!(
1243 "Invalid property element tag name: {tag_name}"
1244 ))
1245 .into());
1246 }
1247 self.build_node_elt(
1248 self.parse_iri(tag_name)?,
1249 base_iri,
1250 language,
1251 #[cfg(feature = "rdf-12")]
1252 base_direction,
1253 id_attr,
1254 node_id_attr,
1255 about_attr,
1256 type_attr,
1257 property_attrs,
1258 #[cfg(feature = "rdf-12")]
1259 rdf_version,
1260 results,
1261 )?
1262 }
1263 RdfXmlNextProduction::PropertyElt { subject } => {
1264 let iri = if *tag_name == *RDF_LI {
1265 let Some(RdfXmlState::NodeElt { li_counter, .. }) = self.state.last_mut()
1266 else {
1267 return Err(RdfXmlSyntaxError::msg(format!(
1268 "Invalid property element tag name: {tag_name}"
1269 ))
1270 .into());
1271 };
1272 *li_counter += 1;
1273 NamedNode::new_unchecked(format!(
1274 "http://www.w3.org/1999/02/22-rdf-syntax-ns#_{li_counter}"
1275 ))
1276 } else if RESERVED_RDF_ELEMENTS.contains(&&*tag_name)
1277 || *tag_name == *RDF_DESCRIPTION
1278 {
1279 return Err(RdfXmlSyntaxError::msg(format!(
1280 "Invalid property element tag name: {tag_name}"
1281 ))
1282 .into());
1283 } else {
1284 self.parse_iri(tag_name)?
1285 };
1286 match parse_type {
1287 RdfXmlParseType::Default => {
1288 if resource_attr.is_some()
1289 || node_id_attr.is_some()
1290 || !property_attrs.is_empty()
1291 {
1292 let object = match (resource_attr, node_id_attr)
1293 {
1294 (Some(resource_attr), None) => NamedOrBlankNode::from(resource_attr),
1295 (None, Some(node_id_attr)) => node_id_attr.into(),
1296 (None, None) => BlankNode::default().into(),
1297 (Some(_), Some(_)) => return Err(RdfXmlSyntaxError::msg("Not both rdf:resource and rdf:nodeID could be set at the same time").into())
1298 };
1299 self.emit_property_attrs(
1300 &object,
1301 property_attrs,
1302 language.as_deref(),
1303 #[cfg(feature = "rdf-12")]
1304 base_direction,
1305 results,
1306 );
1307 if let Some(type_attr) = type_attr {
1308 self.emit_triple(
1309 results,
1310 Triple::new(object.clone(), rdf::TYPE, type_attr),
1311 );
1312 }
1313 RdfXmlState::PropertyElt {
1314 iri,
1315 base_iri,
1316 language,
1317 #[cfg(feature = "rdf-12")]
1318 base_direction,
1319 subject,
1320 object: Some(NodeOrText::Node(object)),
1321 id_attr,
1322 #[cfg(feature = "rdf-12")]
1323 annotation_attr,
1324 #[cfg(feature = "rdf-12")]
1325 annotation_node_id_attr,
1326 datatype_attr,
1327 #[cfg(feature = "rdf-12")]
1328 rdf_version,
1329 }
1330 } else {
1331 RdfXmlState::PropertyElt {
1332 iri,
1333 base_iri,
1334 language,
1335 #[cfg(feature = "rdf-12")]
1336 base_direction,
1337 subject,
1338 object: None,
1339 id_attr,
1340 #[cfg(feature = "rdf-12")]
1341 annotation_attr,
1342 #[cfg(feature = "rdf-12")]
1343 annotation_node_id_attr,
1344 datatype_attr,
1345 #[cfg(feature = "rdf-12")]
1346 rdf_version,
1347 }
1348 }
1349 }
1350 RdfXmlParseType::Literal => RdfXmlState::ParseTypeLiteralPropertyElt {
1351 iri,
1352 base_iri,
1353 language,
1354 #[cfg(feature = "rdf-12")]
1355 base_direction,
1356 subject,
1357 writer: Writer::new(Vec::default()),
1358 id_attr,
1359 #[cfg(feature = "rdf-12")]
1360 annotation_attr,
1361 #[cfg(feature = "rdf-12")]
1362 annotation_node_id_attr,
1363 emit: true,
1364 #[cfg(feature = "rdf-12")]
1365 rdf_version,
1366 },
1367 RdfXmlParseType::Resource => self.build_parse_type_resource_property_elt(
1368 iri,
1369 base_iri,
1370 language,
1371 #[cfg(feature = "rdf-12")]
1372 base_direction,
1373 #[cfg(feature = "rdf-12")]
1374 rdf_version,
1375 subject,
1376 id_attr,
1377 #[cfg(feature = "rdf-12")]
1378 annotation_attr,
1379 #[cfg(feature = "rdf-12")]
1380 annotation_node_id_attr,
1381 results,
1382 ),
1383 RdfXmlParseType::Collection => RdfXmlState::ParseTypeCollectionPropertyElt {
1384 iri,
1385 base_iri,
1386 language,
1387 #[cfg(feature = "rdf-12")]
1388 base_direction,
1389 subject,
1390 objects: Vec::default(),
1391 id_attr,
1392 #[cfg(feature = "rdf-12")]
1393 annotation_attr,
1394 #[cfg(feature = "rdf-12")]
1395 annotation_node_id_attr,
1396 #[cfg(feature = "rdf-12")]
1397 rdf_version,
1398 },
1399 #[cfg(feature = "rdf-12")]
1400 RdfXmlParseType::Triple => RdfXmlState::ParseTypeTriplePropertyElt {
1401 iri,
1402 base_iri,
1403 language,
1404 base_direction,
1405 subject,
1406 id_attr,
1407 #[cfg(feature = "rdf-12")]
1408 annotation_attr,
1409 #[cfg(feature = "rdf-12")]
1410 annotation_node_id_attr,
1411 #[cfg(feature = "rdf-12")]
1412 rdf_version,
1413 triples: Vec::new(),
1414 },
1415 RdfXmlParseType::Other => RdfXmlState::ParseTypeLiteralPropertyElt {
1416 iri,
1417 base_iri,
1418 language,
1419 #[cfg(feature = "rdf-12")]
1420 base_direction,
1421 subject,
1422 writer: Writer::new(Vec::default()),
1423 id_attr,
1424 #[cfg(feature = "rdf-12")]
1425 annotation_attr,
1426 #[cfg(feature = "rdf-12")]
1427 annotation_node_id_attr,
1428 emit: false,
1429 #[cfg(feature = "rdf-12")]
1430 rdf_version,
1431 },
1432 }
1433 }
1434 };
1435 self.state.push(new_state);
1436 Ok(())
1437 }
1438
1439 fn parse_end_event(
1440 &mut self,
1441 event: &BytesEnd<'_>,
1442 results: &mut Vec<Triple>,
1443 ) -> Result<(), RdfXmlParseError> {
1444 if self.in_literal_depth > 0 {
1446 let Some(RdfXmlState::ParseTypeLiteralPropertyElt { writer, .. }) =
1447 self.state.last_mut()
1448 else {
1449 unreachable!()
1450 };
1451 writer.write_event(Event::End(BytesEnd::new(
1452 self.reader.decoder().decode(event.name().as_ref())?,
1453 )))?;
1454 self.in_literal_depth -= 1;
1455 return Ok(());
1456 }
1457
1458 if let Some(current_state) = self.state.pop() {
1459 self.end_state(current_state, results)?;
1460 }
1461 Ok(())
1462 }
1463
1464 fn parse_text_event(&mut self, event: &BytesText<'_>) -> Result<(), RdfXmlParseError> {
1465 let text = event.unescape_with(|e| self.resolve_entity(e))?.to_string();
1466 match self.state.last_mut() {
1467 Some(RdfXmlState::PropertyElt { object, .. }) => {
1468 if is_object_defined(object) {
1469 if text.bytes().all(is_whitespace) {
1470 Ok(()) } else {
1472 Err(
1473 RdfXmlSyntaxError::msg(format!("Unexpected text event: '{text}'"))
1474 .into(),
1475 )
1476 }
1477 } else {
1478 *object = Some(NodeOrText::Text(text));
1479 Ok(())
1480 }
1481 }
1482 Some(RdfXmlState::ParseTypeLiteralPropertyElt { writer, .. }) => {
1483 writer.write_event(Event::Text(BytesText::new(&text)))?;
1484 Ok(())
1485 }
1486 _ => {
1487 if text.bytes().all(is_whitespace) {
1488 Ok(())
1489 } else {
1490 Err(RdfXmlSyntaxError::msg(format!("Unexpected text event: '{text}'")).into())
1491 }
1492 }
1493 }
1494 }
1495
1496 fn resolve_ns_name(
1497 &self,
1498 namespace: ResolveResult<'_>,
1499 local_name: LocalName<'_>,
1500 ) -> Result<String, RdfXmlParseError> {
1501 match namespace {
1502 ResolveResult::Bound(ns) => {
1503 let mut value = Vec::with_capacity(ns.as_ref().len() + local_name.as_ref().len());
1504 value.extend_from_slice(ns.as_ref());
1505 value.extend_from_slice(local_name.as_ref());
1506 Ok(unescape_with(&self.reader.decoder().decode(&value)?, |e| {
1507 self.resolve_entity(e)
1508 })
1509 .map_err(Error::from)?
1510 .to_string())
1511 }
1512 ResolveResult::Unbound => {
1513 Err(RdfXmlSyntaxError::msg("XML namespaces are required in RDF/XML").into())
1514 }
1515 ResolveResult::Unknown(v) => Err(RdfXmlSyntaxError::msg(format!(
1516 "Unknown prefix {}:",
1517 self.reader.decoder().decode(&v)?
1518 ))
1519 .into()),
1520 }
1521 }
1522
1523 #[cfg_attr(feature = "rdf-12", expect(clippy::too_many_arguments))]
1524 fn build_node_elt(
1525 &mut self,
1526 iri: NamedNode,
1527 base_iri: Option<Iri<String>>,
1528 language: Option<String>,
1529 #[cfg(feature = "rdf-12")] base_direction: Option<BaseDirection>,
1530 id_attr: Option<NamedNode>,
1531 node_id_attr: Option<BlankNode>,
1532 about_attr: Option<NamedNode>,
1533 type_attr: Option<NamedNode>,
1534 property_attrs: Vec<(NamedNode, String)>,
1535 #[cfg(feature = "rdf-12")] rdf_version: Option<RdfVersion>,
1536 results: &mut Vec<Triple>,
1537 ) -> Result<RdfXmlState, RdfXmlSyntaxError> {
1538 let subject = match (id_attr, node_id_attr, about_attr) {
1539 (Some(id_attr), None, None) => NamedOrBlankNode::from(id_attr),
1540 (None, Some(node_id_attr), None) => node_id_attr.into(),
1541 (None, None, Some(about_attr)) => about_attr.into(),
1542 (None, None, None) => BlankNode::default().into(),
1543 (Some(_), Some(_), _) => {
1544 return Err(RdfXmlSyntaxError::msg(
1545 "Not both rdf:ID and rdf:nodeID could be set at the same time",
1546 ));
1547 }
1548 (_, Some(_), Some(_)) => {
1549 return Err(RdfXmlSyntaxError::msg(
1550 "Not both rdf:nodeID and rdf:resource could be set at the same time",
1551 ));
1552 }
1553 (Some(_), _, Some(_)) => {
1554 return Err(RdfXmlSyntaxError::msg(
1555 "Not both rdf:ID and rdf:resource could be set at the same time",
1556 ));
1557 }
1558 };
1559
1560 self.emit_property_attrs(
1561 &subject,
1562 property_attrs,
1563 language.as_deref(),
1564 #[cfg(feature = "rdf-12")]
1565 base_direction,
1566 results,
1567 );
1568
1569 if let Some(type_attr) = type_attr {
1570 self.emit_triple(results, Triple::new(subject.clone(), rdf::TYPE, type_attr));
1571 }
1572
1573 if iri != *RDF_DESCRIPTION {
1574 self.emit_triple(results, Triple::new(subject.clone(), rdf::TYPE, iri));
1575 }
1576 Ok(RdfXmlState::NodeElt {
1577 base_iri,
1578 language,
1579 #[cfg(feature = "rdf-12")]
1580 base_direction,
1581 subject,
1582 li_counter: 0,
1583 #[cfg(feature = "rdf-12")]
1584 rdf_version,
1585 })
1586 }
1587
1588 #[cfg_attr(feature = "rdf-12", expect(clippy::too_many_arguments))]
1589 fn build_parse_type_resource_property_elt(
1590 &mut self,
1591 iri: NamedNode,
1592 base_iri: Option<Iri<String>>,
1593 language: Option<String>,
1594 #[cfg(feature = "rdf-12")] base_direction: Option<BaseDirection>,
1595 #[cfg(feature = "rdf-12")] rdf_version: Option<RdfVersion>,
1596 subject: NamedOrBlankNode,
1597 id_attr: Option<NamedNode>,
1598 #[cfg(feature = "rdf-12")] annotation_attr: Option<NamedNode>,
1599 #[cfg(feature = "rdf-12")] annotation_node_id_attr: Option<BlankNode>,
1600 results: &mut Vec<Triple>,
1601 ) -> RdfXmlState {
1602 let object = BlankNode::default();
1603 let triple = Triple::new(subject, iri, object.clone());
1604 self.reify_and_annotation(
1605 &triple,
1606 id_attr,
1607 #[cfg(feature = "rdf-12")]
1608 annotation_attr,
1609 #[cfg(feature = "rdf-12")]
1610 annotation_node_id_attr,
1611 results,
1612 );
1613 self.emit_triple(results, triple);
1614 RdfXmlState::NodeElt {
1615 base_iri,
1616 language,
1617 #[cfg(feature = "rdf-12")]
1618 base_direction,
1619 subject: object.into(),
1620 li_counter: 0,
1621 #[cfg(feature = "rdf-12")]
1622 rdf_version,
1623 }
1624 }
1625
1626 fn end_state(
1627 &mut self,
1628 state: RdfXmlState,
1629 results: &mut Vec<Triple>,
1630 ) -> Result<(), RdfXmlSyntaxError> {
1631 match state {
1632 RdfXmlState::PropertyElt {
1633 iri,
1634 language,
1635 #[cfg(feature = "rdf-12")]
1636 base_direction,
1637 subject,
1638 id_attr,
1639 #[cfg(feature = "rdf-12")]
1640 annotation_attr,
1641 #[cfg(feature = "rdf-12")]
1642 annotation_node_id_attr,
1643 datatype_attr,
1644 object,
1645 ..
1646 } => {
1647 let object = match object {
1648 Some(NodeOrText::Node(node)) => Term::from(node),
1649 Some(NodeOrText::Text(text)) => self
1650 .new_literal(
1651 text,
1652 language,
1653 #[cfg(feature = "rdf-12")]
1654 base_direction,
1655 datatype_attr,
1656 )
1657 .into(),
1658 None => self
1659 .new_literal(
1660 String::new(),
1661 language,
1662 #[cfg(feature = "rdf-12")]
1663 base_direction,
1664 datatype_attr,
1665 )
1666 .into(),
1667 };
1668 let triple = Triple::new(subject, iri, object);
1669 self.reify_and_annotation(
1670 &triple,
1671 id_attr,
1672 #[cfg(feature = "rdf-12")]
1673 annotation_attr,
1674 #[cfg(feature = "rdf-12")]
1675 annotation_node_id_attr,
1676 results,
1677 );
1678 self.emit_triple(results, triple);
1679 }
1680 RdfXmlState::ParseTypeCollectionPropertyElt {
1681 iri,
1682 subject,
1683 id_attr,
1684 #[cfg(feature = "rdf-12")]
1685 annotation_attr,
1686 #[cfg(feature = "rdf-12")]
1687 annotation_node_id_attr,
1688 objects,
1689 ..
1690 } => {
1691 let mut current_node = NamedOrBlankNode::from(rdf::NIL);
1692 for object in objects.into_iter().rev() {
1693 let subject = NamedOrBlankNode::from(BlankNode::default());
1694 self.emit_triple(results, Triple::new(subject.clone(), rdf::FIRST, object));
1695 self.emit_triple(
1696 results,
1697 Triple::new(subject.clone(), rdf::REST, current_node),
1698 );
1699 current_node = subject;
1700 }
1701 let triple = Triple::new(subject, iri, current_node);
1702 self.reify_and_annotation(
1703 &triple,
1704 id_attr,
1705 #[cfg(feature = "rdf-12")]
1706 annotation_attr,
1707 #[cfg(feature = "rdf-12")]
1708 annotation_node_id_attr,
1709 results,
1710 );
1711 self.emit_triple(results, triple);
1712 }
1713 RdfXmlState::ParseTypeLiteralPropertyElt {
1714 iri,
1715 subject,
1716 id_attr,
1717 #[cfg(feature = "rdf-12")]
1718 annotation_attr,
1719 #[cfg(feature = "rdf-12")]
1720 annotation_node_id_attr,
1721 writer,
1722 emit,
1723 ..
1724 } => {
1725 if emit {
1726 let object = writer.into_inner();
1727 if object.is_empty() {
1728 return Err(RdfXmlSyntaxError::msg(format!(
1729 "No value found for rdf:XMLLiteral value of property {iri}"
1730 )));
1731 }
1732 let triple = Triple::new(
1733 subject,
1734 iri,
1735 Literal::new_typed_literal(
1736 str::from_utf8(&object).map_err(|_| {
1737 RdfXmlSyntaxError::msg(
1738 "The XML literal is not in valid UTF-8".to_owned(),
1739 )
1740 })?,
1741 rdf::XML_LITERAL,
1742 ),
1743 );
1744 self.reify_and_annotation(
1745 &triple,
1746 id_attr,
1747 #[cfg(feature = "rdf-12")]
1748 annotation_attr,
1749 #[cfg(feature = "rdf-12")]
1750 annotation_node_id_attr,
1751 results,
1752 );
1753 self.emit_triple(results, triple);
1754 }
1755 }
1756 RdfXmlState::NodeElt { subject, .. } => match self.state.last_mut() {
1757 Some(RdfXmlState::PropertyElt { object, .. }) => {
1758 if is_object_defined(object) {
1759 return Err(RdfXmlSyntaxError::msg(
1760 "Unexpected node, a text value is already present",
1761 ));
1762 }
1763 *object = Some(NodeOrText::Node(subject))
1764 }
1765 Some(RdfXmlState::ParseTypeCollectionPropertyElt { objects, .. }) => {
1766 objects.push(subject)
1767 }
1768 _ => (),
1769 },
1770 RdfXmlState::Doc { .. } | RdfXmlState::Rdf { .. } => (),
1771 #[cfg(feature = "rdf-12")]
1772 RdfXmlState::ParseTypeTriplePropertyElt {
1773 iri,
1774 subject,
1775 id_attr,
1776 annotation_attr,
1777 annotation_node_id_attr,
1778 triples,
1779 rdf_version,
1780 ..
1781 } => {
1782 if rdf_version
1783 .unwrap_or_else(|| self.current_rdf_version())
1784 .supports_triple_term()
1785 {
1786 if triples.len() != 1 {
1787 return Err(RdfXmlSyntaxError::msg(
1788 "rdf:parseType=\"Triple\" can only include a single triple",
1789 ));
1790 }
1791 let triple = Triple::new(subject, iri, triples.into_iter().next().unwrap());
1792 self.reify_and_annotation(
1793 &triple,
1794 id_attr,
1795 annotation_attr,
1796 annotation_node_id_attr,
1797 results,
1798 );
1799 self.emit_triple(results, triple);
1800 }
1801 }
1802 }
1803 Ok(())
1804 }
1805
1806 fn new_literal(
1807 &self,
1808 value: String,
1809 language: Option<String>,
1810 #[cfg(feature = "rdf-12")] base_direction: Option<BaseDirection>,
1811 datatype: Option<NamedNode>,
1812 ) -> Literal {
1813 if let Some(datatype) = datatype {
1814 Literal::new_typed_literal(value, datatype)
1815 } else if let Some(language) =
1816 language.or_else(|| self.current_language().map(ToOwned::to_owned))
1817 {
1818 #[cfg(feature = "rdf-12")]
1819 if let Some(base_direction) = base_direction {
1820 return Literal::new_directional_language_tagged_literal_unchecked(
1821 value,
1822 language,
1823 base_direction,
1824 );
1825 }
1826 Literal::new_language_tagged_literal_unchecked(value, language)
1827 } else {
1828 Literal::new_simple_literal(value)
1829 }
1830 }
1831
1832 fn reify_and_annotation(
1833 &mut self,
1834 triple: &Triple,
1835 statement_id: Option<NamedNode>,
1836 #[cfg(feature = "rdf-12")] annotation: Option<NamedNode>,
1837 #[cfg(feature = "rdf-12")] annotation_node_id: Option<BlankNode>,
1838 results: &mut Vec<Triple>,
1839 ) {
1840 if let Some(statement_id) = statement_id {
1841 self.emit_triple(
1842 results,
1843 Triple::new(statement_id.clone(), rdf::TYPE, rdf::STATEMENT),
1844 );
1845 self.emit_triple(
1846 results,
1847 Triple::new(statement_id.clone(), rdf::SUBJECT, triple.subject.clone()),
1848 );
1849 self.emit_triple(
1850 results,
1851 Triple::new(
1852 statement_id.clone(),
1853 rdf::PREDICATE,
1854 triple.predicate.as_ref(),
1855 ),
1856 );
1857 self.emit_triple(
1858 results,
1859 Triple::new(statement_id, rdf::OBJECT, triple.object.clone()),
1860 );
1861 }
1862 #[cfg(feature = "rdf-12")]
1863 if let Some(annotation) = annotation {
1864 self.emit_triple(
1865 results,
1866 Triple::new(annotation, rdf::REIFIES, triple.clone()),
1867 );
1868 }
1869 #[cfg(feature = "rdf-12")]
1870 if let Some(annotation_node_id) = annotation_node_id {
1871 self.emit_triple(
1872 results,
1873 Triple::new(annotation_node_id, rdf::REIFIES, triple.clone()),
1874 );
1875 }
1876 }
1877
1878 fn emit_property_attrs(
1879 &mut self,
1880 subject: &NamedOrBlankNode,
1881 literal_attributes: Vec<(NamedNode, String)>,
1882 language: Option<&str>,
1883 #[cfg(feature = "rdf-12")] base_direction: Option<BaseDirection>,
1884 results: &mut Vec<Triple>,
1885 ) {
1886 for (literal_predicate, literal_value) in literal_attributes {
1887 self.emit_triple(
1888 results,
1889 Triple::new(
1890 subject.clone(),
1891 literal_predicate,
1892 if let Some(language) = language.or_else(|| self.current_language()) {
1893 #[cfg(feature = "rdf-12")]
1894 if let Some(base_direction) =
1895 base_direction.or_else(|| self.current_base_direction())
1896 {
1897 Literal::new_directional_language_tagged_literal_unchecked(
1898 literal_value,
1899 language,
1900 base_direction,
1901 )
1902 } else {
1903 Literal::new_language_tagged_literal_unchecked(literal_value, language)
1904 }
1905 #[cfg(not(feature = "rdf-12"))]
1906 {
1907 Literal::new_language_tagged_literal_unchecked(literal_value, language)
1908 }
1909 } else {
1910 Literal::new_simple_literal(literal_value)
1911 },
1912 ),
1913 );
1914 }
1915 }
1916
1917 #[cfg_attr(not(feature = "rdf-12"), expect(clippy::unused_self))]
1918 fn emit_triple(&mut self, results: &mut Vec<Triple>, triple: Triple) {
1919 #[cfg(feature = "rdf-12")]
1920 for state in self.state.iter_mut().rev() {
1921 if let RdfXmlState::ParseTypeTriplePropertyElt { triples, .. } = state {
1922 triples.push(triple);
1923 return;
1924 }
1925 }
1926 results.push(triple);
1927 }
1928
1929 fn convert_attribute<'a>(
1930 &self,
1931 attribute: &Attribute<'a>,
1932 ) -> Result<Cow<'a, str>, RdfXmlParseError> {
1933 Ok(attribute
1934 .decode_and_unescape_value_with(self.reader.decoder(), |e| self.resolve_entity(e))?)
1935 }
1936
1937 fn convert_iri_attribute(
1938 &self,
1939 base_iri: Option<&Iri<String>>,
1940 attribute: &Attribute<'_>,
1941 ) -> Result<NamedNode, RdfXmlParseError> {
1942 Ok(self.resolve_iri(base_iri, self.convert_attribute(attribute)?)?)
1943 }
1944
1945 fn resolve_iri(
1946 &self,
1947 base_iri: Option<&Iri<String>>,
1948 relative_iri: Cow<'_, str>,
1949 ) -> Result<NamedNode, RdfXmlSyntaxError> {
1950 if let Some(base_iri) = base_iri.or_else(|| self.current_base_iri()) {
1951 Ok(NamedNode::new_unchecked(
1952 if self.lenient {
1953 base_iri.resolve_unchecked(&relative_iri)
1954 } else {
1955 base_iri.resolve(&relative_iri).map_err(|error| {
1956 RdfXmlSyntaxError::invalid_iri(relative_iri.into(), error)
1957 })?
1958 }
1959 .into_inner(),
1960 ))
1961 } else {
1962 self.parse_iri(relative_iri.into())
1963 }
1964 }
1965
1966 fn parse_iri(&self, relative_iri: String) -> Result<NamedNode, RdfXmlSyntaxError> {
1967 Ok(NamedNode::new_unchecked(if self.lenient {
1968 relative_iri
1969 } else {
1970 Iri::parse(relative_iri.clone())
1971 .map_err(|error| RdfXmlSyntaxError::invalid_iri(relative_iri, error))?
1972 .into_inner()
1973 }))
1974 }
1975
1976 fn current_language(&self) -> Option<&str> {
1977 for state in self.state.iter().rev() {
1978 match state {
1979 RdfXmlState::Doc { .. } => (),
1980 RdfXmlState::Rdf { language, .. }
1981 | RdfXmlState::NodeElt { language, .. }
1982 | RdfXmlState::PropertyElt { language, .. }
1983 | RdfXmlState::ParseTypeCollectionPropertyElt { language, .. }
1984 | RdfXmlState::ParseTypeLiteralPropertyElt { language, .. } => {
1985 if let Some(language) = language {
1986 return Some(language);
1987 }
1988 }
1989 #[cfg(feature = "rdf-12")]
1990 RdfXmlState::ParseTypeTriplePropertyElt { language, .. } => {
1991 if let Some(language) = language {
1992 return Some(language);
1993 }
1994 }
1995 }
1996 }
1997 None
1998 }
1999
2000 #[cfg(feature = "rdf-12")]
2001 fn current_base_direction(&self) -> Option<BaseDirection> {
2002 for state in self.state.iter().rev() {
2003 match state {
2004 RdfXmlState::Doc { .. } => (),
2005 RdfXmlState::Rdf { base_direction, .. }
2006 | RdfXmlState::NodeElt { base_direction, .. }
2007 | RdfXmlState::PropertyElt { base_direction, .. }
2008 | RdfXmlState::ParseTypeCollectionPropertyElt { base_direction, .. }
2009 | RdfXmlState::ParseTypeLiteralPropertyElt { base_direction, .. } => {
2010 if let Some(base_direction) = base_direction {
2011 return Some(*base_direction);
2012 }
2013 }
2014 #[cfg(feature = "rdf-12")]
2015 RdfXmlState::ParseTypeTriplePropertyElt { base_direction, .. } => {
2016 if let Some(base_direction) = base_direction {
2017 return Some(*base_direction);
2018 }
2019 }
2020 }
2021 }
2022 None
2023 }
2024
2025 fn current_base_iri(&self) -> Option<&Iri<String>> {
2026 for state in self.state.iter().rev() {
2027 match state {
2028 RdfXmlState::Doc { base_iri }
2029 | RdfXmlState::Rdf { base_iri, .. }
2030 | RdfXmlState::NodeElt { base_iri, .. }
2031 | RdfXmlState::PropertyElt { base_iri, .. }
2032 | RdfXmlState::ParseTypeCollectionPropertyElt { base_iri, .. }
2033 | RdfXmlState::ParseTypeLiteralPropertyElt { base_iri, .. } => {
2034 if let Some(base_iri) = base_iri {
2035 return Some(base_iri);
2036 }
2037 }
2038 #[cfg(feature = "rdf-12")]
2039 RdfXmlState::ParseTypeTriplePropertyElt { base_iri, .. } => {
2040 if let Some(base_iri) = base_iri {
2041 return Some(base_iri);
2042 }
2043 }
2044 }
2045 }
2046 None
2047 }
2048
2049 #[cfg(feature = "rdf-12")]
2050 fn current_rdf_version(&self) -> RdfVersion {
2051 for state in self.state.iter().rev() {
2052 match state {
2053 RdfXmlState::Doc { .. } => (),
2054 RdfXmlState::Rdf { rdf_version, .. }
2055 | RdfXmlState::NodeElt { rdf_version, .. }
2056 | RdfXmlState::PropertyElt { rdf_version, .. }
2057 | RdfXmlState::ParseTypeCollectionPropertyElt { rdf_version, .. }
2058 | RdfXmlState::ParseTypeLiteralPropertyElt { rdf_version, .. } => {
2059 if let Some(rdf_version) = rdf_version {
2060 return *rdf_version;
2061 }
2062 }
2063 #[cfg(feature = "rdf-12")]
2064 RdfXmlState::ParseTypeTriplePropertyElt { rdf_version, .. } => {
2065 if let Some(rdf_version) = rdf_version {
2066 return *rdf_version;
2067 }
2068 }
2069 }
2070 }
2071 RdfVersion::V11
2072 }
2073
2074 fn resolve_entity(&self, e: &str) -> Option<&str> {
2075 resolve_xml_entity(e).or_else(|| self.custom_entities.get(e).map(String::as_str))
2076 }
2077}
2078
2079fn is_object_defined(object: &Option<NodeOrText>) -> bool {
2080 match object {
2081 Some(NodeOrText::Node(_)) => true,
2082 Some(NodeOrText::Text(t)) => !t.bytes().all(is_whitespace),
2083 None => false,
2084 }
2085}
2086
2087fn is_whitespace(c: u8) -> bool {
2088 matches!(c, b' ' | b'\t' | b'\n' | b'\r')
2089}
2090
2091fn is_utf8(encoding: &[u8]) -> bool {
2092 matches!(
2093 encoding.to_ascii_lowercase().as_slice(),
2094 b"unicode-1-1-utf-8"
2095 | b"unicode11utf8"
2096 | b"unicode20utf8"
2097 | b"utf-8"
2098 | b"utf8"
2099 | b"x-unicode20utf8"
2100 )
2101}
2102
2103#[cfg(feature = "rdf-12")]
2104#[derive(Copy, Clone)]
2105enum RdfVersion {
2106 V11,
2107 V12,
2108 V12Basic,
2109}
2110
2111#[cfg(feature = "rdf-12")]
2112impl RdfVersion {
2113 fn supports_its_dir(self) -> bool {
2114 matches!(self, Self::V12 | Self::V12Basic)
2115 }
2116
2117 fn supports_triple_term(self) -> bool {
2118 matches!(self, Self::V12)
2119 }
2120
2121 fn from_str(value: &str) -> Result<RdfVersion, RdfXmlSyntaxError> {
2122 match value {
2123 "1.1" => Ok(RdfVersion::V11),
2124 "1.2" => Ok(RdfVersion::V12),
2125 "1.2-basic" => Ok(RdfVersion::V12Basic),
2126 _ => Err(RdfXmlSyntaxError::msg(format!(
2127 "The rdf:version value '{value}' is not supported, allowed values are '1.1' and '1.2'"
2128 ))),
2129 }
2130 }
2131}