从nifi中的xml中提取属性

Posted

技术标签:

【中文标题】从nifi中的xml中提取属性【英文标题】:Extract attributes from xml in nifi 【发布时间】:2022-01-18 19:37:04 【问题描述】:

我有这些 xml 文件,我从 ftp 获取它们(使用 list 和 fetch ftp 处理器)。我想从 xml 文件中获取值并用这些值替换文件,因为它是 csv 。 (并使用 putFtp 处理器将它们放回 ftp)

想要的输出是这样的:

"foodate":"somedate","name":"fooid1_foovalue","value":5.44
"foodate":"somedate","name":"fooid1_metrics","value":some-metrics
.
.
.
"foodate":"somedate","name":"fooid2_foovalue","value":2.34
.
.
.

因此,对于每个 id,先写入 foodate 属性,然后再写入 id1、sample - 属性 1、id1、sample - 属性 2 等。

但是每次我不知道名称或属性的数量。只有第一个示例属性将是 foodate。知道如何进行吗?我尝试使用 executeScript 处理器和 js,但它似乎无法识别 DOMParser() 等。

<?xml version="1.0" encoding="ISO-8859-1"?>
<Document Version="2">
    <ExportData lowerBound="2021/11/24 16:58:26" upperBound="2021/11/24 22:58:26">
        <Site name="name" f="">
            <Kapta fooid1="some-number">
                <Infos>
                    <Info>
                        <EndPoint foo="value-name" />
                    </Info>
                </Infos>
                <Samples ordering="desc">
                    <Sample foodate="some-date" foovalue="5.44" metrics="some-metrics" metrics2="metrics-again" value="numbers5" te="numbers" />
                    <Sample foodate="some-date" foovalue="7.45" foom="some-metrics" metrics453="metrics-again" otherattribut="numbers5" att345="numbers" morevalues="numbers" foohdeiurf="numbers" hello="numbers"/>
                </Samples>
            </Kapta>
            <Kapta fooid2="some-number">
                <Infos>
                    <Info>
                        <EndPoint foo="value-name" />
                    </Info>
                </Infos>
                <Samples ordering="desc">
                    <Sample foodate="some-date" foovalue="2.34" metrics="some-metrics" metrics2="metrics-again" value="numbers" te="numbersagain" />
                    <Sample foodate="some-date" foo="99.8" metrics="some-metrics" metrics2="metrics-again" value="numbers" te="numbers" />
                    <Sample foodate="some-date" attr="234.56" someothermetrics="some-metrics" metr="metrics-again" anothervalue="numbers" />
                </Samples>
            </Kapta>
        </Site>
    </ExportData>
</Document>

Thanks a lot for your time and effort!

【问题讨论】:

预期结果是什么? 预期结果类似于 fooid, foodate="some-date" foovalue="some-numbers" metrics="some-metrics" metrics2="metrics-again" value="numbers5" te="numbers" fooid, foodate="some-date" foovalue="some-numbers" foom="some-metrics" metrics453="metrics-again" otherattribut="numbers5" att345="numbers" morevalues="数字" foohdeiurf="numbers" hello="numbers" 你想把它放在哪里?流文件内容或属性?是json格式吗?请编辑您的问题并提供包括预期结果在内的答案。 你说得对,我会编辑我的问题并添加更多详细信息。谢谢 【参考方案1】:

您可以使用 groovy xml 解析器库。根据您的需要有很多选项,请查看this

这是一个实验代码,它从传入流文件的内容中获取 xml,并将一些提取输出为 json 列表。您可以根据自己的要求开发它

请注意,此代码可能不是生产级代码。有关 Nifi 中 Groovy 的更多信息,请参阅ExecuteScript cookbook

import org.apache.nifi.flowfile.FlowFile;
import org.apache.commons.io.IOUtils
import org.apache.nifi.processor.io.InputStreamCallback
import org.apache.nifi.processor.io.StreamCallback
import java.nio.charset.StandardCharsets
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import groovy.xml.dom.DOMCategory
import groovy.json.JsonGenerator

def flowFile

try 
    
    flowFile = session.get()
    
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = null

    session.read(flowFile, inputStream ->
        doc =  dBuilder.parse(inputStream)
     as InputStreamCallback)
    
    def root = doc.documentElement
    def sb = new StringBuilder()
    def jsonGenerator = new JsonGenerator.Options().disableUnicodeEscaping().build()
    
    // get a specific attribute
    use(DOMCategory) 
         root['ExportData']['Site']['Kapta']['Infos']['Info']['*'].findAll  node ->
            def data = new LinkedHashMap()
            data.NodeName = node.name()
            data.foodate = node['@foo']
            sb.append(jsonGenerator.toJson(data))
            sb.append('\n')
           
    
    
    // get all attributes of Sample under Samples
    use(DOMCategory) 
        root['ExportData']['Site']['Kapta']['Samples']['*'].findAll  node ->
            def data = new LinkedHashMap()
            data.NodeName = node.name()
            def attributesMap = node.attributes()
            for (int x = 0; x < attributesMap.getLength(); x++) 
                data.AttrName = attributesMap.item(x).getNodeName();
                data.AttrValue = attributesMap.item(x).getNodeValue();
                sb.append(jsonGenerator.toJson(data))
                sb.append('\n')
            
                    
       
       
    
    flowFile = session.write(flowFile, inputStream, outputStream ->
        outputStream.write(sb.toString().getBytes(StandardCharsets.UTF_8))
     as StreamCallback)
    
    session.transfer(flowFile, REL_SUCCESS)
    
 catch (Exception e) 
    log.error('',e)
    session.transfer(flowFile, REL_FAILURE)





   

【讨论】:

感谢您的回复!实际上,我通过 ftp 获取文件并将它们放回原处。我不确定看到日志很热,因为您的脚本显示了那里的值。这是我的错,因为我没有描述所需的输出。我想用 xml 中的值替换我从 ftp 获得的 xml 文件。对于每个 foid 我想写一行 id 和 sample values 。例如 fooid1, sample1 - attributes fooid1, sample2 - attributes fooid2,sample1 - attributes etc 日志可以在 /log 文件夹下的 nifi-app.log 文件中看到。无论如何,我编辑了关于您的更新的答案。祝你好运。 谢谢!我会尽量开发现有代码以满足我的需要,但它对开始很有帮助! 感谢您抽出宝贵时间回答我的问题。根据上面的代码,如何打印文件中的所有属性名称和值? 我想你事先并不知道属性并且想要动态地获取它们。我编辑了我的答案。

以上是关于从nifi中的xml中提取属性的主要内容,如果未能解决你的问题,请参考以下文章

从具有 Oracle db 中的属性的 XML 中提取 NCLOB 中的 XML 数据

如何使用 PHP 从 XML“链接”标签中提取“href”属性?

从 xml 的元素中提取命名空间属性

NiFi 的 PutHiveStreaming 处理器不会从 hive-site.xml 中获取属性

从多个 XML 行中提取数据

在 PIG 中使用 xpath 提取 XML 中的属性值