Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

citygml: 名前空間周りの修正、テスト追加など #141

Merged
merged 8 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion nusamai-citygml/macros/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn generate_citygml_impl_for_struct(
let struct_ident = &derive_input.ident;
let mut typename = String::from(stringify!(derive_input.ident));
let mut ty = StereoType::Feature;
let mut allow_extra = true; // FIXME
let mut allow_extra = false;

for attr in &derive_input.attrs {
if !attr.path().is_ident(CITYGML_ATTR_IDENT) {
Expand Down Expand Up @@ -202,6 +202,17 @@ fn generate_citygml_impl_for_struct(
Some(self.#field_ident)
};

Ok(())
} else if meta.path.is_ident("generics") {
chlid_arms.push(quote! {
b"gen:dateAttribute" => st.skip_current_element(),
b"gen:doubleAttribute" => st.skip_current_element(),
b"gen:genericAttributeSet" => st.skip_current_element(),
b"gen:intAttribute" => st.skip_current_element(),
b"gen:measureAttribute" => st.skip_current_element(),
b"gen:stringAttribute" => st.skip_current_element(),
b"gen:uriAttribute" => st.skip_current_element(),
});
Ok(())
} else {
Err(meta.error("unrecognized argument"))
Expand Down
8 changes: 8 additions & 0 deletions nusamai-citygml/macros/src/type_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ fn modify(ty: &StereoType, args: &FeatureArgs, input: &mut DeriveInput) -> Resul
pub valid_to: Option<nusamai_citygml::Date> // TODO: DateTime (CityGML 3.0)
},
);
// TODO: not implemented yet
add_named_field(
fields,
quote! {
#[citygml(generics)]
pub generic_attribute: Option<i32> // FIXME:
},
);
}
}
}
Expand Down
89 changes: 88 additions & 1 deletion nusamai-citygml/src/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use quick_xml::name::{Namespace, ResolveResult};

pub const GML31_NS: Namespace = Namespace(b"http://www.opengis.net/gml");

/// Normalize a XML namaespace URI to a well-known prefix.
/// Normalizes `quick_xml::name::ResolveResult` to the well-known prefix.
///
/// e.g. `"http://www.opengis.net/citygml/2.0"` -> `"core:"`
#[inline]
Expand All @@ -29,6 +29,7 @@ pub fn wellknown_prefix_from_nsres<'a>(ns: &ResolveResult<'a>) -> &'a [u8] {
b"cityobjectgroup/2.0" => b"grp:",
b"landuse/2.0" => b"luse:",
b"transportation/2.0" => b"tran:",
b"texturedsurface/2.0" => b"tex:", // deprecated
b"vegetation/2.0" => b"veg:",
b"waterbody/2.0" => b"wtr:",
b"tunnel/2.0" => b"tun:",
Expand All @@ -48,6 +49,12 @@ pub fn wellknown_prefix_from_nsres<'a>(ns: &ResolveResult<'a>) -> &'a [u8] {
b"urf/2.0" => b"urf:",
_ => b"unsupported:",
}
} else if name == b"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" {
// OASIS xAL 2.0
b"xAL:"
} else if name == b"http://www.w3.org/1999/xlink" {
// xlink
b"xlink:"
} else {
// PLATEAU 1.x
match *name {
Expand All @@ -67,3 +74,83 @@ pub fn wellknown_prefix_from_nsres<'a>(ns: &ResolveResult<'a>) -> &'a [u8] {
ResolveResult::Unknown(_name) => b"unknown:",
}
}

#[cfg(test)]
mod tests {
#[test]
fn normalized_prefix() {
use super::*;
use quick_xml::{events::Event, NsReader};

let data = r#"
<?xml version="1.0" encoding="UTF-8"?>
<core2ns:core
xmlns:gml31ns="http://www.opengis.net/gml"
xmlns:core2ns="http://www.opengis.net/citygml/2.0"
xmlns:grp2ns="http://www.opengis.net/citygml/cityobjectgroup/2.0"
xmlns:bldg2ns="http://www.opengis.net/citygml/building/2.0"
xmlns:brid2ns="http://www.opengis.net/citygml/bridge/2.0"
xmlns:tran2ns="http://www.opengis.net/citygml/transportation/2.0"
xmlns:frn2ns="http://www.opengis.net/citygml/cityfurniture/2.0"
xmlns:wtr2ns="http://www.opengis.net/citygml/waterbody/2.0"
xmlns:veg2ns="http://www.opengis.net/citygml/vegetation/2.0"
xmlns:tun2ns="http://www.opengis.net/citygml/tunnel/2.0"
xmlns:tex2ns="http://www.opengis.net/citygml/texturedsurface/2.0"
xmlns:app2ns="http://www.opengis.net/citygml/appearance/2.0"
xmlns:gen2ns="http://www.opengis.net/citygml/generics/2.0"
xmlns:dem2ns="http://www.opengis.net/citygml/relief/2.0"
xmlns:luse2ns="http://www.opengis.net/citygml/landuse/2.0"
xmlns:uro3ns="https://www.geospatial.jp/iur/uro/3.0"
xmlns:urf3ns="https://www.geospatial.jp/iur/urf/3.0"
xmlns:uro2ns="https://www.geospatial.jp/iur/uro/2.0"
xmlns:urf2ns="https://www.geospatial.jp/iur/urf/3.0"
xmlns:uro15ns="https://www.chisou.go.jp/tiiki/toshisaisei/itoshisaisei/iur/uro/1.5"
xmlns:urf15ns="https://www.chisou.go.jp/tiiki/toshisaisei/itoshisaisei/iur/urf/1.5"
xmlns:xAL2ns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"
xmlns:xlinkns="http://www.w3.org/1999/xlink"
>
<!-- namespace_prefix:wellknown_prefix -->
<foobar:unknown />
<gml31ns:gml />
<core2ns:core />
<grp2ns:grp />
<bldg2ns:bldg />
<brid2ns:brid />
<tran2ns:tran />
<frn2ns:frn />
<wtr2ns:wtr />
<veg2ns:veg />
<tun2ns:tun />
<tex2ns:tex />
<app2ns:app />
<gen2ns:gen />
<dem2ns:dem />
<luse2ns:luse />
<uro3ns:uro />
<urf3ns:urf />
<uro2ns:uro />
<urf2ns:urf />
<uro15ns:uro />
<urf15ns:urf />
<xAL2ns:xAL />
</core2ns:core>
"#;

let mut reader = NsReader::from_str(data);
reader.trim_text(true);
reader.expand_empty_elements(true);
loop {
match reader.read_resolved_event() {
Ok((ns, Event::Start(ref e))) => {
let wellknown = std::str::from_utf8(wellknown_prefix_from_nsres(&ns)).unwrap();
let localname = e.local_name();
let expected = String::from_utf8_lossy(localname.as_ref()) + ":";
assert_eq!(wellknown, expected);
}
Ok((_, Event::Eof)) => break,
Ok(_) => {}
Err(e) => panic!("{:?}", e),
}
}
}
}
17 changes: 8 additions & 9 deletions nusamai-plateau/src/codelist/xml.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::collections::HashMap;
use std::io::BufRead;

use nusamai_citygml::ParseError;
use quick_xml::events::Event;
use quick_xml::name::Namespace;
use quick_xml::name::ResolveResult::Bound;

const GML_NS: Namespace = Namespace(b"http://www.opengis.net/gml");
use nusamai_citygml::namespace::GML31_NS;
use nusamai_citygml::ParseError;

#[derive(Debug)]
pub struct Definition {
Expand Down Expand Up @@ -66,11 +65,11 @@ fn parse_definition<R: BufRead>(
depth += 1;
let (nsres, localname) = reader.resolve_element(start.name());
match (depth, nsres, localname.as_ref()) {
(2, Bound(GML_NS), b"name") => {
(2, Bound(GML31_NS), b"name") => {
identifier = Some(expect_text(reader, buf)?);
depth -= 1;
}
(2, Bound(GML_NS), b"description") => {
(2, Bound(GML31_NS), b"description") => {
value = Some(expect_text(reader, buf)?);
depth -= 1;
}
Expand Down Expand Up @@ -122,20 +121,20 @@ pub fn parse_dictionary<R: BufRead>(
depth += 1;
let (nsres, localname) = reader.resolve_element(start.name());
match (depth, nsres, localname.as_ref()) {
(1, Bound(GML_NS), b"Dictionary") => {}
(1, Bound(GML31_NS), b"Dictionary") => {}
(1, _, _) => {
return Err(ParseError::SchemaViolation(format!(
"<Dictionary> is expected, but found {}",
String::from_utf8_lossy(localname.as_ref())
)))
}
(2, Bound(GML_NS), b"name") => {
(2, Bound(GML31_NS), b"name") => {
// Just ignore it for now.
let _name = expect_text(&mut reader, &mut buf)?;
depth -= 1;
}
(2, Bound(GML_NS), b"dictionaryEntry") => {}
(3, Bound(GML_NS), b"Definition") => {
(2, Bound(GML31_NS), b"dictionaryEntry") => {}
(3, Bound(GML31_NS), b"Definition") => {
parse_definition(&mut reader, &mut definitions, &mut buf, &mut buf2)?;
depth -= 1;
}
Expand Down