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 元素支持附加属性, pathpath 应为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)" }
  ]
}