Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
1fbe16e1
Commit
1fbe16e1
authored
Dec 12, 2025
by
Matthias Betz
Browse files
add xml validation to streaming processing
parent
82888d4b
Pipeline
#12286
passed with stage
in 2 minutes and 15 seconds
Changes
10
Pipelines
1
Show whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/CheckReport.java
View file @
1fbe16e1
...
...
@@ -22,6 +22,7 @@ import java.io.BufferedReader;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.nio.file.Path
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -65,7 +66,11 @@ public class CheckReport {
private
Map
<
String
,
FeatureReport
>
featureReports
;
public
static
CheckReport
load
(
String
file
)
throws
CheckReportParseException
{
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
FileReader
(
file
)))
{
return
load
(
Path
.
of
(
file
));
}
public
static
CheckReport
load
(
Path
path
)
throws
CheckReportParseException
{
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
FileReader
(
path
.
toFile
())))
{
CheckReport
report
=
(
CheckReport
)
getContext
().
createUnmarshaller
().
unmarshal
(
new
InputSource
(
reader
));
enrichReportStructure
(
report
);
return
report
;
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlConsumer.java
View file @
1fbe16e1
...
...
@@ -32,6 +32,5 @@ public interface CityGmlConsumer {
}
// public void endOfFile();
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java
View file @
1fbe16e1
...
...
@@ -131,9 +131,9 @@ public class CityGmlParser {
private
static
CityGMLContext
context
;
private
static
List
<
QName
>
chunkProperties
=
new
ArrayList
<>();
static
{
System
.
setProperty
(
"javax.xml.transform.TransformerFactory"
,
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"
);
System
.
setProperty
(
"javax.xml.transform.TransformerFactory"
,
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"
);
FACTORY
=
SAXParserFactory
.
newInstance
();
try
{
FACTORY
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
false
);
...
...
@@ -149,7 +149,7 @@ public class CityGmlParser {
private
CityGmlParser
()
{
}
public
static
synchronized
CityGMLContext
g
etContext
()
{
public
static
synchronized
CityGMLContext
s
et
up
Context
()
{
if
(
context
==
null
)
{
try
{
context
=
CityGMLContext
.
newInstance
(
CityGmlParser
.
class
.
getClassLoader
());
...
...
@@ -168,13 +168,17 @@ public class CityGmlParser {
}
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* The nested parse uses an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}, which
* is not connected to the database.
* The nested parse uses an
* {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache
* UnconnectedCache}, which is not connected to the database.
* <p/>
* Nested parsing should only be used for accessing Features in auxiliary, small CityGML files, e.g. parsing of
* {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject LibraryObject} files.
* Nested parsing should only be used for accessing Features in auxiliary, small
* CityGML files, e.g. parsing of
* {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject
* LibraryObject} files.
*
* @param filePath String path to the file
* @param config Configuration of the parser
...
...
@@ -188,10 +192,12 @@ public class CityGmlParser {
}
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* Features are held in a non-persistent, embedded Database with an in-memory
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
* @param filePath String path to the file
* @param config Configuration of the parser
...
...
@@ -204,12 +210,13 @@ public class CityGmlParser {
return
parseCityGmlFile
(
filePath
,
config
,
null
,
null
);
}
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* Features are held in a non-persistent, embedded Database with an in-memory
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
* @param filePath String path to the file
* @param config Configuration of the parser
...
...
@@ -224,10 +231,12 @@ public class CityGmlParser {
}
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* Features are held in a non-persistent, embedded Database with an in-memory
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
* @param filePath String path to the file
* @param config Configuration of the parser
...
...
@@ -243,18 +252,22 @@ public class CityGmlParser {
}
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* Features are held in a non-persistent, embedded Database with an in-memory
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
* @param filePath String path to the file
* @param config Configuration of the parser
* @param l Listener hook for tracking of parsing progress
* @param handler Validation handler for GML-file validation
* @param verbose If verbosity is enabled the parser will write info logs to the logger
* @param unconnected If true the parser will use an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}
* to collect the parsed CityObjects
* @param verbose If verbosity is enabled the parser will write info logs to
* the logger
* @param unconnected If true the parser will use an
* {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache
* UnconnectedCache} to collect the parsed CityObjects
* @return A {@link CityDoctorModel} object with the parsed Features
* @throws CityGmlParseException if parsing of the CityGML-file failed
* @throws InvalidGmlFileException if the GMLValidationHandler found an error
...
...
@@ -262,13 +275,12 @@ public class CityGmlParser {
private
static
CityDoctorModel
parseCityGmlFile
(
String
filePath
,
ParserConfiguration
config
,
ProgressListener
l
,
GMLValidationHandler
handler
,
boolean
verbose
,
boolean
unconnected
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
CityGMLContext
context
=
g
etContext
();
CityGMLContext
context
=
s
et
up
Context
();
Path
file
=
Paths
.
get
(
filePath
);
List
<
String
>
validationIssues
=
Collections
.
emptyList
();
if
(
config
.
getValidate
())
{
validationIssues
=
validateFile
(
context
,
handler
,
file
);
validationIssues
=
validateFile
(
handler
,
file
);
}
try
{
parseEpsgCodeFromFile
(
file
,
config
,
verbose
);
CityGMLInputFactory
in
=
context
.
createCityGMLInputFactory
()
...
...
@@ -288,8 +300,6 @@ public class CityGmlParser {
}
}
public
static
void
streamCityGml
(
String
file
,
ParserConfiguration
config
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
Path
f
=
Paths
.
get
(
file
);
...
...
@@ -342,18 +352,18 @@ public class CityGmlParser {
private
static
void
readAndDiscardFeatures
(
Path
file
,
ParserConfiguration
config
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
file
,
false
);
readAndDiscardModel
(
mapper
,
ois
,
cityObjectConsumer
,
outputFile
);
readAndDiscardModel
(
mapper
,
ois
,
cityObjectConsumer
,
outputFile
,
config
,
file
);
}
private
static
void
readAndDiscardModel
(
Citygml3FeatureMapper
mapper
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
getContext
();
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
,
ParserConfiguration
config
,
Path
file
)
throws
CityGMLReadException
{
setupContext
();
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
CityGMLChunkWriter
writer
=
null
;
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
CityDoctorModel
model
=
mapper
.
getModel
();
boolean
isInitialized
=
false
;
while
(
reader
.
hasNext
())
{
...
...
@@ -418,7 +428,7 @@ public class CityGmlParser {
if
(
outputFile
==
null
)
{
return
null
;
}
CityGMLContext
gmlContext
=
CityGmlParser
.
g
etContext
();
CityGMLContext
gmlContext
=
CityGmlParser
.
s
et
up
Context
();
CityGMLVersion
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
version
);
CityGMLChunkWriter
writer
=
factory
.
createCityGMLChunkWriter
(
new
File
(
outputFile
),
...
...
@@ -432,8 +442,8 @@ public class CityGmlParser {
}
private
static
CityDoctorModel
readAndKeepFeatures
(
ParserConfiguration
config
,
Path
file
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
boolean
verbose
,
boolean
unconnected
)
throws
CityGMLReadException
{
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
boolean
verbose
,
boolean
unconnected
)
throws
CityGMLReadException
{
return
readAndKeepModel
(
new
Citygml3FeatureMapper
(
config
,
file
,
unconnected
),
inputFactory
,
ois
,
verbose
);
}
...
...
@@ -448,7 +458,7 @@ public class CityGmlParser {
CityModel
cgmlModel
=
null
;
CityDoctorModel
cdModel
=
mapper
.
getModel
();
AutoCloseable
parsingContext
=
cdModel
.
getCache
().
startParsingMode
();
try
(
parsingContext
){
try
(
parsingContext
)
{
List
<
AbstractCityObject
>
queuedObjects
=
new
ArrayList
<>();
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
...
...
@@ -473,7 +483,7 @@ public class CityGmlParser {
if
(
cgmlModel
==
null
)
{
// Add object to queue till the CityModel has been parsed
queuedObjects
.
add
(
aco
);
}
else
if
(!
cdModel
.
containsGmlId
(
id
)){
}
else
if
(!
cdModel
.
containsGmlId
(
id
))
{
cgmlModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
}
}
...
...
@@ -486,7 +496,8 @@ public class CityGmlParser {
mapper
.
setCityModel
(
new
CityModel
());
for
(
AbstractCityObject
aco
:
queuedObjects
)
{
if
(!
cdModel
.
containsGmlId
(
aco
.
getId
()))
{
mapper
.
getModel
().
getCityModel
().
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
mapper
.
getModel
().
getCityModel
().
getCityObjectMembers
()
.
add
(
new
AbstractCityObjectProperty
(
aco
));
}
}
}
...
...
@@ -506,7 +517,8 @@ public class CityGmlParser {
}
}
private
static
void
parseEpsgCodeFromFile
(
Path
file
,
ParserConfiguration
config
,
boolean
verbose
)
throws
CityGmlParseException
{
private
static
void
parseEpsgCodeFromFile
(
Path
file
,
ParserConfiguration
config
,
boolean
verbose
)
throws
CityGmlParseException
{
try
(
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
file
.
toFile
())))
{
parseEpsgCodeFromStream
(
bis
,
config
,
verbose
);
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
...
...
@@ -673,11 +685,12 @@ public class CityGmlParser {
return
CRS_FACTORY
.
createFromParameters
(
crsName
,
params
.
toArray
(
new
String
[
0
]));
}
private
static
List
<
String
>
validateFile
(
CityGMLContext
context
,
GMLValidationHandler
handler
,
Path
file
)
public
static
List
<
String
>
validateFile
(
GMLValidationHandler
handler
,
Path
file
)
throws
CityGmlParseException
{
if
(
handler
==
null
)
{
handler
=
new
GMLValidationHandler
();
}
setupContext
();
try
{
SchemaHandler
schemaHandler
=
new
ValidationSchemaHandler
(
context
.
getDefaultSchemaHandler
());
readAdditionalSchemaDefinitions
(
context
,
file
,
schemaHandler
);
...
...
@@ -696,8 +709,7 @@ public class CityGmlParser {
private
static
void
readAdditionalSchemaDefinitions
(
CityGMLContext
context
,
Path
file
,
SchemaHandler
schemaHandler
)
throws
CityGmlParseException
{
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
())
.
withSchemaHandler
(
schemaHandler
)
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
()).
withSchemaHandler
(
schemaHandler
)
.
createReader
(
file
))
{
reader
.
nextTag
();
}
catch
(
Exception
e
)
{
...
...
@@ -715,5 +727,4 @@ public class CityGmlParser {
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/writer/CityGMLWriterUtils.java
View file @
1fbe16e1
...
...
@@ -65,7 +65,7 @@ public class CityGMLWriterUtils {
}
public
static
void
writeCityModel
(
String
file
,
CityDoctorModel
model
)
throws
CityDoctorWriteException
{
CityGMLContext
gmlContext
=
CityGmlParser
.
g
etContext
();
CityGMLContext
gmlContext
=
CityGmlParser
.
s
et
up
Context
();
CityModel
cModel
=
model
.
getCityModel
();
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
model
.
getCityGMLVersion
());
try
(
CityGMLWriter
writer
=
factory
.
createCityGMLWriter
(
new
File
(
file
)))
{
...
...
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/parser/CityGml3ParserTest.java
View file @
1fbe16e1
...
...
@@ -37,7 +37,7 @@ public class CityGml3ParserTest {
@Test
public
void
testGetContext
()
{
CityGMLContext
context
=
CityGmlParser
.
g
etContext
();
CityGMLContext
context
=
CityGmlParser
.
s
et
up
Context
();
List
<
ADE
>
ades
=
ADERegistry
.
getInstance
().
getADEs
();
ADE
ade
=
ades
.
get
(
0
);
assertEquals
(
QualityADEContext
.
class
,
ade
.
getClass
());
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
View file @
1fbe16e1
...
...
@@ -65,6 +65,7 @@ import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError
;
import
de.hft.stuttgart.citydoctor2.check.error.SchematronError
;
import
de.hft.stuttgart.citydoctor2.check.error.XMLValidationError
;
import
de.hft.stuttgart.citydoctor2.checkresult.utility.CheckReportWriteException
;
import
de.hft.stuttgart.citydoctor2.checks.CheckContainer
;
import
de.hft.stuttgart.citydoctor2.checks.CheckPrototype
;
...
...
@@ -919,6 +920,20 @@ public class Checker {
XmlStreamReporter
xmlReporter
=
getXmlReporter
(
config
,
xmlBos
,
fileName
);
PdfStreamReporter
pdfReporter
=
getPdfReporter
(
config
,
pdfBos
,
fileName
);
// XML validation
if
(
config
.
isUseStreaming
()
&&
(
xmlReporter
!=
null
||
pdfReporter
!=
null
))
{
List
<
String
>
validationIssues
=
CityGmlParser
.
validateFile
(
null
,
inputFile
.
toPath
());
for
(
String
xmlError
:
validationIssues
)
{
XMLValidationError
validationError
=
new
XMLValidationError
(
xmlError
);
if
(
xmlReporter
!=
null
)
{
xmlReporter
.
reportGlobalError
(
validationError
);
}
if
(
pdfReporter
!=
null
)
{
pdfReporter
.
reportGlobalError
(
validationError
);
}
}
}
// execute schematron first
SvrlContentHandler
handler
=
executeSchematronValidationIfAvailable
(
config
,
inputFile
);
CityGmlConsumer
con
=
new
StreamCityGmlConsumer
(
c
,
xmlReporter
,
pdfReporter
,
handler
,
config
,
l
);
...
...
CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java
View file @
1fbe16e1
...
...
@@ -18,6 +18,22 @@
*/
package
de.hft.stuttgart.citydoctor2.check
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
org.apache.commons.io.FileUtils
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
de.hft.stuttgart.citydoctor2.CityDoctorValidation
;
import
de.hft.stuttgart.citydoctor2.checkresult.CheckReport
;
import
de.hft.stuttgart.citydoctor2.checkresult.GlobalErrorStatistics
;
...
...
@@ -31,22 +47,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import
de.hft.stuttgart.citydoctor2.parser.CityGmlParser
;
import
de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
org.apache.commons.io.FileUtils
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
/**
* @author Matthias Betz
...
...
@@ -76,7 +76,8 @@ public class CheckerTest {
}
@Test
public
void
testChecker
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
public
void
testChecker
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
File
f
=
folder
.
newFile
();
File
f2
=
folder
.
newFile
();
...
...
@@ -98,7 +99,8 @@ public class CheckerTest {
}
@Test
public
void
testStreaming
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
public
void
testStreaming
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
File
f
=
folder
.
newFile
();
File
f2
=
folder
.
newFile
();
File
f3
=
folder
.
newFile
();
...
...
@@ -125,6 +127,27 @@ public class CheckerTest {
}
}
@Test
public
void
testStreamingWithXMLValidation
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
,
CheckReportParseException
{
File
f2
=
folder
.
newFile
();
try
{
String
[]
args
=
new
String
[
6
];
args
[
0
]
=
"-in"
;
args
[
1
]
=
"src/test/resources/SimpleSolid_SrefBS_XMLInvalid.gml"
;
args
[
2
]
=
"-config"
;
args
[
3
]
=
"src/test/resources/testConfigWithStreamingWithValidation.yml"
;
args
[
4
]
=
"-xmlReport"
;
args
[
5
]
=
f2
.
getAbsolutePath
();
CityDoctorValidation
.
main
(
args
);
assertTrue
(
f2
.
exists
());
CheckReport
checkReport
=
CheckReport
.
load
(
f2
.
toPath
());
assertEquals
(
1
,
checkReport
.
getValidationResults
().
getGlobalErrors
().
size
());
}
finally
{
f2
.
delete
();
}
}
@Test
public
void
testReportCreation
()
throws
IOException
,
CityGmlParseException
,
InvalidGmlFileException
{
Path
tmpDir
=
null
;
...
...
@@ -134,8 +157,8 @@ public class CheckerTest {
Path
xmlPath
=
tmpDir
.
resolve
(
"report.xml"
);
Path
pdfPath
=
tmpDir
.
resolve
(
"report.pdf"
);
File
features
=
new
File
(
"src/test/resources/feature_types.gml"
);
CityDoctorModel
model
=
CityGmlParser
.
nestedCityGmlFileParse
(
features
.
toString
(),
new
ParserConfiguration
(
8
,
false
));
CityDoctorModel
model
=
CityGmlParser
.
nestedCityGmlFileParse
(
features
.
toString
(),
new
ParserConfiguration
(
8
,
false
));
assertNotNull
(
model
);
Checker
checker
=
new
Checker
(
model
);
checker
.
runChecks
();
...
...
@@ -174,12 +197,10 @@ public class CheckerTest {
assertEquals
(
1
,
globError
.
getNumErrorCityFurniture
());
assertEquals
(
1
,
globError
.
getNumErrorGenericCityObjects
());
}
catch
(
CheckReportParseException
e
)
{
fail
(
"Report should be valid file"
);
}
}
finally
{
if
(
tmpDir
!=
null
)
{
FileUtils
.
deleteDirectory
(
tmpDir
.
toFile
());
...
...
CityDoctorParent/CityDoctorValidation/src/test/resources/SimpleSolid_SrefBS_XMLInvalid.gml
0 → 100644
View file @
1fbe16e1
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel
xmlns:core=
"http://www.opengis.net/citygml/2.0"
xmlns:gen=
"http://www.opengis.net/citygml/generics/2.0"
xmlns:bldg=
"http://www.opengis.net/citygml/building/2.0"
xmlns:app=
"http://www.opengis.net/citygml/appearance/2.0"
xmlns:dem=
"http://www.opengis.net/citygml/relief/2.0"
xmlns:gml=
"http://www.opengis.net/gml"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd"
>
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert.
Fehler in der Reihenfolge der Attribute.
CityGML 2.0
Gebäudevolumen: 56,25 m3
12.12.2025
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building
gml:id=
"_Simple_BD.1"
>
<gen:stringAttribute
name=
"averageStoreyHeight"
>
<gen:value>
2.5
</gen:value>
</gen:stringAttribute>
<gml:name>
falsche Reihenfolge
</gml:name>
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.1"
/>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.2"
/>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.3"
/>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.4"
/>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.5"
/>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.6"
/>
<gml:surfaceMember
xlink:href=
"#_Simple_BD.1_PG.7"
/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface
gml:id=
"_Simple_BD.1_WallSurface_1"
>
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.2"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.2_LR.1"
>
<gml:posList
srsDimension=
"3"
>
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface
gml:id=
"_Simple_BD.1_WallSurface_2"
>
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.3"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.3_LR.1"
>
<gml:posList
srsDimension=
"3"
>
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface
gml:id=
"_Simple_BD.1_WallSurface_3"
>
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.4"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.4_LR.1"
>
<gml:posList
srsDimension=
"3"
>
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface
gml:id=
"_Simple_BD.1_WallSurface_4"
>
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.5"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.5_LR.1"
>
<gml:posList
srsDimension=
"3"
>
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface
gml:id=
"_Simple_BD.1_RoofSurface_1"
>
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.6"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.6_LR.1"
>
<gml:posList
srsDimension=
"3"
>
10.0 10.0 3.0
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.7"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.7_LR.1"
>
<gml:posList
srsDimension=
"3"
>
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface
gml:id=
"_Simple_BD.1_GroundSurface_1"
>
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon
gml:id=
"_Simple_BD.1_PG.1"
>
<gml:exterior>
<gml:LinearRing
gml:id=
"_Simple_BD.1_PG.1_LR.1"
>
<gml:posList
srsDimension=
"3"
>
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
CityDoctorParent/CityDoctorValidation/src/test/resources/testConfigWithStreamingWithValidation.yml
0 → 100644
View file @
1fbe16e1
globalParameters
:
numberOfRoundingPlaces
:
8
schematronFilePath
:
src/test/resources/schematronTest.xml
useStreaming
:
true
requirements
:
R_GE_R_TOO_FEW_POINTS
:
enabled
:
true
R_GE_R_NOT_CLOSED
:
enabled
:
true
R_GE_R_CONSECUTIVE_POINTS_SAME
:
enabled
:
true
R_GE_R_SELF_INTERSECTION
:
enabled
:
true
R_GE_S_MULTIPLE_CONNECTED_COMPONENTS
:
enabled
:
true
R_GE_P_INTERIOR_DISCONNECTED
:
enabled
:
true
R_GE_P_INTERSECTING_RINGS
:
enabled
:
true
R_GE_P_NON_PLANAR
:
enabled
:
false
parameters
:
# one of ("distance", "angle", "both")
type
:
distance
distanceTolerance
:
0.01
angleTolerance
:
0.1
R_GE_P_HOLE_OUTSIDE
:
enabled
:
true
R_GE_P_ORIENTATION_RINGS_SAME
:
enabled
:
true
R_GE_P_INNER_RINGS_NESTED
:
enabled
:
true
R_GE_S_TOO_FEW_POLYGONS
:
enabled
:
true
R_GE_S_NOT_CLOSED
:
enabled
:
true
R_GE_S_NON_MANIFOLD_EDGE
:
enabled
:
true
R_GE_S_POLYGON_WRONG_ORIENTATION
:
enabled
:
true
R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION
:
enabled
:
true
R_GE_S_NON_MANIFOLD_VERTEX
:
enabled
:
true
R_GE_S_SELF_INTERSECTION
:
enabled
:
true
\ No newline at end of file
CityDoctorParent/Extensions/CityDoctorHealer/src/main/java/de/hft/stuttgart/citydoctor2/healer/Healer.java
View file @
1fbe16e1
...
...
@@ -289,7 +289,7 @@ public class Healer {
private
byte
[]
writeCityGml
(
AbstractCityObject
aco
)
throws
CityGMLWriteException
{
CityModel
model
=
new
CityModel
();
model
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
CityGMLContext
context
=
CityGmlParser
.
g
etContext
();
CityGMLContext
context
=
CityGmlParser
.
s
et
up
Context
();
CityGMLOutputFactory
outputFactory
=
context
.
createCityGMLOutputFactory
(
CityGMLVersion
.
v2_0
);
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
try
(
CityGMLWriter
writer
=
outputFactory
.
createCityGMLWriter
(
out
))
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment