pdvrieze / xmlutil

XML Serialization library for Kotlin
https://pdvrieze.github.io/xmlutil/
Apache License 2.0
363 stars 30 forks source link

Wrong order of contents and string parsing #188

Closed meedovique closed 7 months ago

meedovique commented 8 months ago

There are some problems with parsing landXML files

I use this class to get points:

@Serializable
@XmlSerialName("P")
data class LandXMLPoint(
    val id: Int,
    @XmlValue val dataStr: String,
)

but dataStr sometimes connect to other id (see screen), also it's hard to resolve dataStr correctly when there is negative number there

Screenshot from 2023-10-27 10-19-07

pdvrieze commented 8 months ago

I've tried to reproduce this in a simple way, but can't reproduce it. Could you provide simple reproducing project/test case. I'm not sure where you have problems with negative numbers. The - character is just like any other letter for the parser.

The only possible explanation could be if you were using JVM with a custom xml parsing library (it is a service) where this library somehow breaks parsing. In that case, try parsing with XML.decodeFromString(XmlStreaming.newGenericReader(data))

meedovique commented 8 months ago

Thanks for the quick response

Screens: There is a string with correct value before decoding and with 202,.. number after

Screenshot from 2023-10-28 21-24-02 Screenshot from 2023-10-28 21-23-21

I used this options:

@OptIn(ExperimentalXmlUtilApi::class)
val xml = XML {
    unknownChildHandler = XmlConfig.IGNORING_UNKNOWN_CHILD_HANDLER
    xmlVersion = XmlVersion.XML10
}

val serializer = serializer<LandXML>()

Here classes:

@Serializable
@XmlSerialName("LandXML", "http://www.landxml.org/schema/LandXML-1.2", "")
data class LandXML(
    val date: String,
    val time: String,
    val units: LandXMLUnits,
    val coordinateSystem: LandXMLCoordinateSystem?,
    val project: LandXMLProject,
    val application: LandXMLApplication,
    val surfaces: LandXMLSurfaces,
)

@Serializable
@XmlSerialName("Units")
data class LandXMLUnits(
    val metric: LandXMLMetric?,
)

@Serializable
@XmlSerialName("Metric")
data class LandXMLMetric(
    val linearUnit: String,
    val areaUnit: String,
    val volumeUnit: String,
    val temperatureUnit: String,
    val pressureUnit: String,
    val angularUnit: String,
    val directionUnit: String,
)

@Serializable
@XmlSerialName("CoordinateSystem")
data class LandXMLCoordinateSystem(
    val desc: String,
    val horizontalDatum: String,
    val verticalDatum: String,
    val datum: String,
    val horizontalCoordinateSystemName: String,
    val projectedCoordinateSystemName: String,
    val verticalCoordinateSystemName: String,
)

@Serializable
@XmlSerialName("Project")
data class LandXMLProject(
    val name: String,
)

@Serializable
@XmlSerialName("Application")
data class LandXMLApplication(
    val name: String,
    val manufacturer: String,
    val desc: String,
    val manufacturerURL: String,
    val timeStamp: String,
)

@Serializable
@XmlSerialName("Surfaces")
data class LandXMLSurfaces(
    val name: String?,
    val surface: LandXMLSurface,
)

@Serializable
@XmlSerialName("Surface")
data class LandXMLSurface(
    val name: String,
    val definition: LandXMLDefinition,
)

@Serializable
@XmlSerialName("Definition")
data class LandXMLDefinition(
    val surfType: String,
    val points: LandXMLPoints,
    val triangles: LandXMLTriangles,
)

@Serializable
@XmlSerialName("Pnts")
data class LandXMLPoints(
    val points: List<LandXMLPoint>,
)

@Serializable
@XmlSerialName("P")
data class LandXMLPoint(
    val id: Int,
    @XmlValue val dataStr: String,
)

@Serializable
@XmlSerialName("Faces")
data class LandXMLTriangles(
    val triangles: List<LandXMLTriangle>,
)

@Serializable
@XmlSerialName("F")
data class LandXMLTriangle(
    @XmlValue val dataStr: String,
)

And here is a file with xml:

TIN with Alignment.zip

pdvrieze commented 8 months ago

I had a look. The problem is that the file contains 2 surfaces, and the second screenshot displays the second surface: "Diff_Mill_2", but the top screenshot displays the first one. To fix this, just parse as list:

    data class LandXMLSurfaces(
        val name: String?,
        val surfaces: List<LandXMLSurface>,
    )

I did notice that parsing content as text lists doesn't work yet. I'll try to fix that in a new version.

meedovique commented 8 months ago

Thanks a lot for your help!

pdvrieze commented 8 months ago

I've just pushed support for parsing lists of primitives from XmlValue elements (which would replace your dataStr members). There should be an automated snapshot supporting it soon.