在实现LoST协议时,我们如何使用Java从findService请求解组大地位置?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在实现LoST协议时,我们如何使用Java从findService请求解组大地位置?相关的知识,希望对你有一定的参考价值。

我知道我对一个协议有一个非常具体的问题,世界上很少有人可能正在努力。提前感谢您阅读并试图帮助我。

上下文:我目前正在实现LoST:RFC 5222中描述的位置到服务转换协议。特别是,我正在解析一个XML文档的FindService请求。如果您感到好奇,可以在RFC中找到该文档的架构,但对此问题并不重要。

我正在使用Java和JAXB。我已经能够使用XSD实现各种请求而没有任何问题,所以我相信我的Maven插件和代码生成方法是正确的。

问题:我的问题是我在解组可以在FindService请求中找到的特定类型的位置时遇到问题。该类型是“geodetic-2d”位置类型,由以下附加文档定义:

GEOPRIV Presence Information Data Format Location Object (PIDF-LO) Usage Clarification, Considerations, and Recommendations geoshape profile

我得到的错误是javax.xml.bind.UnmarshalException:意外元素(uri:“http://www.opengis.net/pidflo/1.0”,local:“Circle”)。预期的元素是http://www.opengis.net/gml} ArcByCenterPoint> [...]

本消息的基本内容是unmarshaller期待来自gml命名空间的对象,但却找到了pidflo。 XML对象如下所示:

<gs:Circle srsName="urn:ogc:def:crs:EPSG::4326"
xmlns:gs="http://www.opengis.net/pidflo/1.0"
xmlns:gml="http://www.opengis.net/gml">
<gml:pos>
42.5463 -73.2512
</gml:pos>
<gml:radius uom="urn:ogc:def:uom:EPSG::9001">
850.24
</gml:radius>
</gs:Circle>

此示例来自OpenGIS文档,并且是正确的。请注意如何将两个名称空间混合在一起。 “Circle”确实来自pidflo名称空间,我已经验证了XSD是正确的。

问题:我想知道如何从查找服务“位置”对象解组大地位置。

为了简化这个问题,我想如果有人可以帮助我解组上面显示的Circle XML对象,我应该能够用其他类型来解决我的问题。

为了使这个问题更实用,请考虑以下代码:

public static void main(String[] args) {
    JAXBContext gmlOrCivicContext = null;
    try {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        gmlOrCivicContext = JAXBContext.newInstance(net.opengis.pidflo._1.CircleType.class);
        Marshaller marshaller = gmlOrCivicContext.createMarshaller();
        ObjectFactory objectFactory = new ObjectFactory();
        JAXBElement<CircleType> circle = objectFactory.createCircle(new CircleType());
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(circle, byteArrayOutputStream);

        String x = byteArrayOutputStream.toString();
        System.out.println(x);

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(x.getBytes());
        Unmarshaller unmarshaller = gmlOrCivicContext.createUnmarshaller();
        Object unmarshal = unmarshaller.unmarshal(byteArrayInputStream);
    } catch (JAXBException e) {
        e.printStackTrace();
    }

}

运行这个程序时,我能够编组并打印出Circle对象,但是我无法解组它(即使我使用完全相同的上下文!)。

以下是上面显示的代码的控制台输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Circle xmlns:ns1="http://www.opengis.net/gml" xmlns:ns2="http://www.opengis.net/pidflo/1.0"/>

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.opengis.net/pidflo/1.0", local:"Circle"). Expected elements are <{http://www.opengis.net/gml}ArcByCenterPoint>,[...]
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:182)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:351)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3132)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:852)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)

有谁知道为什么我能够编组对象而不是解组它?

如果我能提供更多信息,请告诉我。

  • 萨科
答案

我找到了为什么我的JAXB生成的类可以编组XML而不是解组它的原因。我想我会在这里分享答案,以防有人在使用LoST(以及它使用的命名空间名称)的类似问题中运行。

问题出在opengis pidflo geoshape xml名称空间的生成包名称中:xmlns:gs =“http://www.opengis.net/pidflo/1.0”。

它会自动转换为以下java包名:net.opengis.pidflo._1.CircleType.class

“_1”中的前导下划线与Java不兼容。

修复包名后,所有代码都开始工作。

我更改了我的Maven JAXB插件配置,以使用“packageName”指令强制geoshape包避免使用下划线。我还在每个xsd的基础上分割代码生成,为每个代码设置正确的包,我使用clearOutputDir指令来避免每个执行过度重写彼此生成的输出。

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>2.3.1</version>
            <executions>
                <execution>
                    <id>xjc-gml</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <sources>src/main/xsd/geoshape/0.1.0/GML-pidf-lo-shape.xsd</sources>
                        <packageName>net.opengis.pidflo</packageName>
                        <clearOutputDir>false</clearOutputDir>
                    </configuration>
                </execution>
                <execution>
                    <id>xjc-civic</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <sources>src/main/xsd/civicAddr.xsd</sources>
                        <packageName>ietf.params.xml.ns.pidf.geopriv10.civicaddr</packageName>
                        <clearOutputDir>false</clearOutputDir>
                    </configuration>
                </execution>
                <execution>
                    <id>xjc-lost</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <sources>src/main/xsd/lost.xsd</sources>
                        <packageName>ietf.params.xml.ns.lost1</packageName>
                        <clearOutputDir>false</clearOutputDir>
                    </configuration>
                </execution>
            </executions>

        </plugin>

问候,

  • 萨科

以上是关于在实现LoST协议时,我们如何使用Java从findService请求解组大地位置?的主要内容,如果未能解决你的问题,请参考以下文章

使用C#实现欧姆龙PLC FINS协议读取

使用C#实现欧姆龙PLC FINS协议读取

如何关闭一个TCP连接

如何才能正确的关闭Socket连接

FinsTCP协议报文详细分析

Java中wait()方法为什么要放在同步块中?(lost wake-up 问题)