9.8. XML转换器¶
XML转换器处理XML文件。若要使用XML转换器,请指定 type = "xml"
在您的转换器定义中。
9.8.1. 配置¶
XML转换器支持以单行模式或多行模式解析文件。在单行模式中,输入文件的每一行都应该是有效的XML文档;在多行模式中,整个输入文件应该是单个有效的XML文档。为了支持XPath表达式,每个XML文档都被完全解析到内存中。对于大型文档,这可能需要相当长的时间和内存。因此,在可能的情况下,通常最好使用单行模式。线路模式可由指定 options.line-mode = "single"
或 options.line-mode = "multi"
在您的转换器定义中。如果未指定任何内容,则使用单行模式。
默认情况下,XML转换器将尝试使用Saxon XML工厂(如果可用)。Saxon通常比默认的Java实现快得多。如果需要,可以通过设置指定解析器 xpath-factory
的完全限定类名。 javax.xml.xpath.XPathFactory
实施。
如果XML源文档包含命名空间,则可能需要通过 xml-namespaces
元素。看见 使用Saxon处理命名空间 ,见下文。
XML转换器支持通过XSD文档进行架构验证。若要启用验证,请使用 xsd
元素。此文件必须在类路径上可用。没有根据XSD进行验证的输入文档将引发异常。
由于单个XML文档可能包含多个特性,因此XML解析器支持指向每个特性元素的XPath表达式。这可以使用 feature-path
元素。
这个 fields
元素支持附加属性, path
。 path
应为XPath表达式,它可能相对于 feature-path
(如果上面已定义)或对文档根目录而言是绝对的。这个 path
表达式的计算结果为字符串,并在 transform
元素为 $0
。
9.8.2. XML复合转换器¶
复合转换器可以在单个流中处理不同的XML格式。若要使用复合转换器,请指定 type = "composite-xml"
在您的转换器定义中。
复合转换器可以定义顶级选项、字段等,与普通的XML转换器相同。这些值将由每个子转换器继承。如果每个子级都是唯一的,则不在顶层定义任何内容都是有效的。
复合转换器必须定义 converters
元素,它是嵌套的XML转换器定义的数组。除了标准配置之外,每个嵌套的转换器还必须具有 predicate
元素,该元素确定要为每个XML文档使用哪个转换器。传递到谓词中的值将是解析后的XML文档(可用 $0
),所以通常该谓词将利用 xpath
函数(下图)。看见 谓词 以获取有关谓词的更多详细信息。
9.8.3. XML转换函数¶
这个 transform
元素支持引用 path
表达方式: $0
。每个值都将是一个字符串。
除了中的标准函数之外 变换函数概述 中,该XML转换器提供以下特定于XML的函数:
9.8.3.1. XPath¶
这个 xpath
函数允许您在字段上下文之外计算XPath表达式。一般而言, path
在使用XML字段时首选表达式,但 xpath
函数对于复合转换器谓词非常有用,如上所述。
这个 xpath
函数接受2到4个参数。第一个参数是字符串形式的XPath表达式。第二个参数是要对其应用XPath表达式的XML文档。通常情况下,正在考虑的文档为 $0
。第三个参数是 javax.xml.xpath.XPathFactory
实施。如果省略,将使用默认的Saxon工厂。第四个参数是 java.util.Map
包含XPath求值可能需要的任何XML命名空间,如果不使用命名空间,则可以省略这些命名空间。一般而言, ParseMap 函数才能创建适当的名称空间映射。看见 使用Saxon处理命名空间 ,见下文。
9.8.3.2. XmlToString¶
这将把一个XML元素转换成一个字符串。它对于快速表示复杂对象非常有用,例如,为了基于行的散列创建特征ID。
9.8.4. 用法示例¶
假定以下SimpleFeatureType:
geomesa.sfts.example = {
attributes = [
{ name = "number", type = "Integer" }
{ name = "color", type = "String" }
{ name = "weight", type = "Double" }
{ name = "source", type = "String" }
{ name = "geom", type = "Point" }
]
}
和以下XML文档:
<?xml version="1.0"?>
<doc>
<DataSource>
<name>myxml</name>
</DataSource>
<Feature>
<number>123</number>
<geom>
<lat>12.23</lat>
<lon>44.3</lon>
</geom>
<color>red</color>
<physical height="5'11" weight="127.5"/>
</Feature>
<Feature>
<number>456</number>
<geom>
<lat>20.3</lat>
<lon>33.2</lon>
</geom>
<color>blue</color>
<physical height="h2" weight="150"/>
</Feature>
</doc>
您可以使用以下转换器进行摄取:
geomesa.converters.myxml = {
type = "xml"
id-field = "uuid()"
feature-path = "Feature" // optional path to feature elements
xsd = "example.xsd" // optional xsd file to validate input
xpath-factory = "net.sf.saxon.xpath.XPathFactoryImpl"
options = {
line-mode = "multi" // or "single"
}
fields = [
{ name = "number", path = "number", transform = "$0::integer" }
{ name = "color", path = "color", transform = "trim($0)" }
{ name = "weight", path = "physical/@weight", transform = "$0::double" }
{ name = "source", path = "/doc/DataSource/name/text()" }
{ name = "lat", path = "geom/lat", transform = "$0::double" }
{ name = "lon", path = "geom/lon", transform = "$0::double" }
{ name = "geom", transform = "point($lon, $lat)" }
]
}
9.8.5. 使用Saxon处理命名空间¶
使用默认的Java XPath工厂,通常可以忽略XML名称空间。但是,Saxon工厂要求声明名称空间。您可以通过以下方式完成此操作 xml-namespaces
配置。
示例XML:
<?xml version="1.0"?>
<foo:doc xmlns:foo="http://example.com/foo" xmlns:bar="http://example.com/bar">
<foo:DataSource>
<foo:name>myxml</foo:name>
</foo:DataSource>
<foo:Feature>
<foo:number>123</foo:number>
<bar:geom>
<bar:lat>12.23</bar:lat>
<bar:lon>44.3</bar:lon>
</bar:geom>
<foo:color>red</foo:color>
<foo:physical height="5'11" weight="127.5"/>
</foo:Feature>
</foo:doc>
配置:
{
type = "xml"
id-field = "uuid()"
feature-path = "foo:Feature" // optional path to feature elements
xsd = "example.xsd" // optional xsd file to validate input
xpath-factory = "net.sf.saxon.xpath.XPathFactoryImpl"
options = {
line-mode = "multi" // or "single"
}
xml-namespaces = {
foo = "http://example.com/foo"
bar = "http://example.com/bar"
}
fields = [
{ name = "number", path = "foo:number", transform = "$0::integer" }
{ name = "color", path = "foo:color", transform = "trim($0)" }
{ name = "weight", path = "foo:physical/@weight", transform = "$0::double" }
{ name = "source", path = "/foo:doc/foo:DataSource/foo:name/text()" }
{ name = "lat", path = "bar:geom/bar:lat", transform = "$0::double" }
{ name = "lon", path = "bar:geom/bar:lon", transform = "$0::double" }
{ name = "geom", transform = "point($lon, $lat)" }
]
}