我有一个文本文件,其中包含多个如下所示的xml:
<queryResponse><entity><devicesDTO><clearedAlarms>1</clearedAlarms><warningAlarms>0</warningAlarms></devicesDTO></entity></queryResponse>
<queryResponse><entity><devicesDTO><clearedAlarms>2</clearedAlarms><warningAlarms>2</warningAlarms></devicesDTO></entity></queryResponse>
我想将每一行都转换为一个csv:
clearedAlarms, warningAlarms
1, 0
2, 2
这是我现在拥有的,仅使我能够解析xml并输出csv。该文件现在实际上已更改,我应该正在读取包含多个xml的txt文件
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use XML::Simple;
#Elements, that I want see in my csv
my @Fields = qw{clearedAlarms warningAlarms};
open(my $out, '>', 'test.csv') or die "Output: $!\n";
print $out join(',', @Fields) . "\n";
my $xml = XMLin('test.xml', ForceArray => ['entity']);
foreach my $entity ( @{ $xml->{entity} } ) {
print Dumper $entity;
}
foreach my $entity ( @{ $xml->{entity} } ) {
print $out join( ',', @{ $entity->{devicesDTO} }{@Fields} ) . "\n";
}
答案 0 :(得分:2)
这是Perl口号的由来:“做的方式不止一种!”如果您不想使用xml模块(如前所述,该文件实际上已经更改,并且我应该读取包含多个xml的txt文件),则可以使用https://metacpan.org/pod/File::Grep mdoule(查找与一系列文件中的模式和相关功能)以进行文件操作。以及https://metacpan.org/pod/Text::CSV_XS(https://metacpan.org/pod/Text::CSV_XS)此模块提供了与csv操作相关的更多功能,您可以根据需要使用它们。
fmap阻止列表 使用BLOCK作为映射功能,对LIST中的文件执行映射操作。来自BLOCK的结果将被添加到调用结束时返回的列表中。
csv这是针对简单(用户)界面的高级功能。可用于读取/解析CSV文件或流(默认行为)或生成文件或写入流(定义out属性)。
import 'package:flutter/material.dart';
import 'story.dart';
import 'dart:math';
class StoryBrain {
static Random random = Random();
int textNumber;
bool gameTypeIsClasic = false;
static List<Story> textListClasic = [
Story(
"text content 2",
"göm",
),
Story(
"text content 1",
"öv",
),
Story(
"text content 3",
"göm",
),
Story("text content 4", "öv")
];
static List<Story> textListTemel = [
Story(
"text content 1",
"göm",
),
Story(
"text content 2",
"öv",
),
Story(
"text content 3",
"göm",
),
Story("text content 4", "öv")
];
int heat = 1;
StoryBrain() {
if (gameTypeIsClasic == true) {
random.nextInt(textListClasic.length - 1);
} else {
random.nextInt(textListTemel.length - 1);
}
}
void changeNumber() {
if (gameTypeIsClasic == true) {
textNumber = random.nextInt(textListClasic.length - 1);
} else {
textNumber = random.nextInt(textListTemel.length - 1);
}
}
String getText() {
if (gameTypeIsClasic == true) {
return textListClasic[textNumber].textContent;
} else {
return textListTemel[textNumber].textContent;
}
}
String getTextType() {
if (gameTypeIsClasic == true) {
return textListClasic[textNumber].textType;
} else {
return textListTemel[textNumber].textType;
}
}
Color setColor() {
if (getTextType() == "öv") {
return Colors.blue;
} else {
return Colors.red;
}
}
String updateHeat() {
if (getTextType() == "öv") {
if (heat > 1 && heat < 20) {
heat = heat - 1;
} else if (heat > 20 && heat < 100) {
heat -= 10;
} else if (heat > 200 && heat < 500) {
heat -= 25;
} else if (heat > 500) {
heat = (heat ~/ 3);
} else {
heat = heat;
}
} else {
if (heat < 1000) {
heat = heat * 2;
} else {
heat += 100;
}
}
return heat.toString() + "x";
}
Color changeHeatBarColor() {
if (heat >= 50 && heat < 100) {
return Colors.orange;
} else if (heat >= 100 && heat < 500) {
return Colors.redAccent;
} else if (heat > 500) {
return Colors.red[800];
} else {
return Colors.blue;
}
}
}
输出(如果您打开$ csv_file文件)
const { session } = win.webContents;
session.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
delete details.requestHeaders["User-Agent"];
callback({ requestHeaders: details.requestHeaders });
});
session.webRequest.onHeadersReceived(filter, (details, callback) => {
details.responseHeaders["access-control-allow-origin"] = "*";
callback({ responseHeaders: details.responseHeaders });
});
答案 1 :(得分:1)
鉴于XML模式的简单性,使用AnyData更容易做到
例如:
#!/usr/bin/perl
# This script converts a XML file to CSV format.
# Load the AnyData XML to CSV conversion modules
use XML::Parser;
use XML::Twig;
use AnyData;
my $input_xml = "test.xml";
my $output_csv = "test.csv";
$flags->{record_tag} = 'ITEM';
adConvert( 'XML', $input_xml, 'CSV', $output_csv, $flags );
将您的数据结构(XML)转换为:
clearedAlarms, warningAlarms
1, 0
2, 2
答案 2 :(得分:0)
如果您的文件结构始终相同,则实际上不需要XML解析器。但是您也不需要任何其他东西。您可以将该输入文件视为稍微复杂的CSV文件,其中包含奇怪的定界符。
split
使用模式将字符串转换为字符串列表。默认情况下,它将占用定界符匹配项,因此此匹配项消失。我们可以使用看起来像XML标签的模式作为模式。请注意,我如何将qr//
与不是斜杠/
的定界符一起使用,以使其更具可读性,因为它避免了在结束标记中转义可选的斜杠/
。
split qr{</?[^>]+>}, '<foo>123</foo>';
这将产生一个看起来像这样的数据结构(使用Data::Printer来产生输出):
[
[0] "",
[2] 123
]
第一个元素是一个空字符串,表示在分隔符模式的第一个匹配项之前缺少任何其他字符。我们需要过滤掉它们。使用grep
可以轻松做到这一点。
grep { $_ ne q{} } split qr{</?[^>]+>}, '<foo>123</foo>';
现在我们的输出很好,很干净。
[
[0] 123
]
我们现在要做的就是将其应用于完整文件。由于我们的数据仅包含几个数字,因此在这种情况下无需使用Text :: CSV。
use strict;
use warnings;
use feature 'say';
while (<DATA>) {
chomp;
say join ',', grep { $_ ne q{} } split qr{</?[^>]+>};
}
__DATA__
<queryResponse><entity><devicesDTO><clearedAlarms>1</clearedAlarms><warningAlarms>0</warningAlarms></devicesDTO></entity></queryResponse>
<queryResponse><entity><devicesDTO><clearedAlarms>2</clearedAlarms><warningAlarms>2</warningAlarms></devicesDTO></entity></queryResponse>
请记住,这里我们可以使用模式匹配,因为我们实际上并不解析XML。如果要进行任何真正的XML解析,请不要使用正则表达式!