使用perl无法正确嵌套从JSON创建的XML
我正在尝试使用perl脚本将JSON数据转换为XML。但是转换后的JSON没有预期的标记。下面是我使用的输入、代码和收到的输出使用perl无法正确嵌套从JSON创建的XML,json,xml,perl,nested-attributes,data-conversion,Json,Xml,Perl,Nested Attributes,Data Conversion,我正在尝试使用perl脚本将JSON数据转换为XML。但是转换后的JSON没有预期的标记。下面是我使用的输入、代码和收到的输出 {"status": "Success", "output": {"product_artifacts": [ {"variant_name": "test_var", "artifacts": [ {"artifact_create
{"status": "Success",
"output":
{"product_artifacts":
[
{"variant_name": "test_var",
"artifacts":
[
{"artifact_created": "10-25-19 15:52:02",
"artifact_download_link": "http://abc:rt/ ",
"artifact_digital_size": 123,
"artifact_number": "123/234",
"artifact_revision": "AB1"}
]
}
]
},
"message":
[]
}
上面的Json在传递到下面的Perl脚本时,没有按预期创建XML:
Perl脚本:
#!/app/perl/5.16.2/LMWP3/bin/perl
use strict;
use warnings;
binmode STDOUT, ":utf8";
use utf8;
use JSON;
use XML::Simple;
# Read input file in json format
my $json = '
{"status": "Success",
"output":
{"product_artifacts":
[
{"variant_name": "test_var",
"artifacts":
[
{"artifact_created": "10-25-19 15:52:02",
"artifact_download_link": "http://abc:rt/ ",
"artifact_digital_size": 123,
"artifact_number": "123/234",
"artifact_revision": "AB1"}
]
}
]
},
"message":
[]
}';
# Convert JSON format to perl structures
my $data = decode_json($json);
# Output as XML
print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
print XMLout($data);
print "\n";
#/app/perl/5.16.2/LMWP3/bin/perl
严格使用;
使用警告;
binmode标准输出“:utf8”;
使用utf8;
使用JSON;
使用XML::Simple;
#读取json格式的输入文件
我的美元是多少
{“状态”:“成功”,
“产出”:
{“产品_工件”:
[
{“variant_name”:“test_var”,
“文物”:
[
{“创造的神器”:“10-25-19 15:52:02”,
“工件下载链接”:http://abc:rt/ ",
“工件数字尺寸”:123,
“工件编号”:“123/234”,
“工件修订”:“AB1”}
]
}
]
},
“信息”:
[]
}';
#将JSON格式转换为perl结构
my$data=decode_json($json);
#输出为XML
打印“\n”;
打印XMLout(数据);
打印“\n”;
实际输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<opt status="Success">
<output>
<product_artifacts variant_name="test_var">
<artifacts artifact_created="10-25-19 15:52:02" artifact_digital_size="9293792" artifact_download_link="http://abc:rt " artifact_number="123/234" artifact_revision="AC" />
</product_artifacts>
</output>
</opt>
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<status>Success</status>
<output>
<product_artifacts>
<variant_name>test_var</variant_name>
<artifacts>
<artifact_created>10-25-19 15:52:02</artifact_created>
<artifact_download_link>http://asd:rt </artifact_download_link>
<artifact_digital_size>123</artifact_digital_size>
<artifact_number>1234</artifact_number>
<artifact_revision>AC</artifact_revision>
</artifacts>
</product_artifacts>
</output>
<message/>
</root>
预期输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<opt status="Success">
<output>
<product_artifacts variant_name="test_var">
<artifacts artifact_created="10-25-19 15:52:02" artifact_digital_size="9293792" artifact_download_link="http://abc:rt " artifact_number="123/234" artifact_revision="AC" />
</product_artifacts>
</output>
</opt>
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<status>Success</status>
<output>
<product_artifacts>
<variant_name>test_var</variant_name>
<artifacts>
<artifact_created>10-25-19 15:52:02</artifact_created>
<artifact_download_link>http://asd:rt </artifact_download_link>
<artifact_digital_size>123</artifact_digital_size>
<artifact_number>1234</artifact_number>
<artifact_revision>AC</artifact_revision>
</artifacts>
</product_artifacts>
</output>
<message/>
</root>
成功
测试变量
10-25-19 15:52:02
http://asd:rt
123
1234
自动控制
有人能帮我解决哪里出了问题吗目前还没有解决方案 让我提供一个可能的简单解决方案,不使用任何perl模块
use strict;
use warnings;
use feature 'say';
use JSON;
binmode STDOUT, ":utf8";
use utf8;
my $json = '
{"status": "Success",
"output":
{ "product_artifacts":
[
{
"variant_name": "test_var",
"artifacts":
[
{
"artifact_created": "10-25-19 15:52:02",
"artifact_download_link": "http://abc:rt/ ",
"artifact_digital_size": 123,
"artifact_number": "123/234",
"artifact_revision": "AB1"
}
]
}
]
},
"message":[]
}';
# Convert JSON format to perl structures
my $data = decode_json($json);
say json2xml($data);
sub json2xml {
my $data = shift;
my $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
$xml .= "<root>\n";
$xml .= j2x($data,1);
$xml .= "</root>\n";
return $xml;
}
sub j2x {
my $json = shift;
my $depth = shift;
my $xml;
my $indent = 2;
my $space = ' ' x ($depth*$indent);
while( my($k,$v) = each %{$json} ) {
if( ref $v eq 'HASH' ) {
$xml .= $space . "<$k>\n";
$xml .= j2x($v,$depth+1);
$xml .= $space . "</$k>\n";
} elsif ( ref $v eq 'ARRAY' ) {
$xml .= $space . "<$k>\n";
foreach my $e (@{$v}) {
$xml .= j2x($e,$depth+1);
}
$xml .= $space . "</$k>\n";
} else {
$xml .= $space . "<$k>$v</$k>\n";
}
}
return $xml;
}
使用严格;
使用警告;
使用特征“说”;
使用JSON;
binmode标准输出“:utf8”;
使用utf8;
我的美元是多少
{“状态”:“成功”,
“产出”:
{“产品_工件”:
[
{
“变量名称”:“测试变量”,
“文物”:
[
{
“创造的神器”:“10-25-19 15:52:02”,
“工件下载链接”:http://abc:rt/ ",
“工件数字尺寸”:123,
“工件编号”:“123/234”,
“工件修订”:“AB1”
}
]
}
]
},
“信息”:[]
}';
#将JSON格式转换为perl结构
my$data=decode_json($json);
比如json2xml($data);
子json2xml{
我的$data=shift;
my$xml=“\n”;
$xml.=“\n”;
$xml.=j2x($data,1);
$xml.=“\n”;
返回$xml;
}
子j2x{
我的$json=shift;
我的$depth=shift;
我的$xml;
我的$indent=2;
my$space=''x($depth*$indent);
而(my($k,$v)=每个%{$json}){
如果(参考$v等式“哈希”){
$xml.=$space.“\n”;
$xml.=j2x($v,$depth+1);
$xml.=$space.“\n”;
}elsif(参考$v均衡器“阵列”){
$xml.=$space.“\n”;
每个我的$e(@{$v}){
$xml.=j2x($e,$depth+1);
}
$xml.=$space.“\n”;
}否则{
$xml.=$space.“$v\n”;
}
}
返回$xml;
}
输出与所需略有不同,因为代码未考虑空xml元素(在这种情况下为空JSON数组)
成功
测试变量
123/234
10-25-19 15:52:02
AB1
123
http://abc:rt/
注意:在OP的post中,JSON和所需输出不匹配,因此生成的输出是post中给出的JSON数据的表示形式。Perl数据结构不直接映射到XML。例如,位于某个位置的hashref可以由标记上的属性或嵌套标记表示,这些标记本身可能具有属性、标记或文本。因此,要以您想要的方式格式化输出,一种方法是使用模板来定义您想要的结构,例如使用
使用严格;
使用警告;
使用Mojo::模板;
my$tmpl={output}{product_artifacts}}){
{variant_name}%>
可用于此目的
use strict;
use warnings;
use Mojo::DOM;
my $dom = Mojo::DOM->new->xml(1)->parse('<?xml version="1.0" encoding="UTF-8" ?><root/>');
my $root = $dom->at('root');
$root->append_content($dom->new_tag('status', $data->{status}));
$root->append_content($dom->new_tag('output'));
my $output = $root->at('output');
$output->append_content($dom->new_tag('product_artifacts'));
my $product_artifacts = $output->at('product_artifacts');
foreach my $variant (@{$data->{output}{product_artifacts}}) {
$product_artifacts->append_content($dom->new_tag('variant_name', $variant->{variant_name}));
$product_artifacts->append_content($dom->new_tag('artifacts'));
my $artifacts = $product_artifacts->at('artifacts');
foreach my $artifact (@{$variant->{artifacts}}) {
foreach my $key (sort keys %$artifact) {
$artifacts->append_content($dom->new_tag($key, $artifact->{$key}));
}
}
}
$root->append_content($dom->new_tag('message', $data->{message}));
my $xml = $dom->to_string;
使用严格;
使用警告;
使用Mojo::DOM;
my$dom=Mojo::dom->new->xml(1)->parse(“”);
my$root=$dom->at('root');
$root->append_content($dom->new_标记('status',$data->{status}));
$root->append_content($dom->new_标记('output'));
my$output=$root->at('output');
$output->append_content($dom->new_标记('product_artifacts');
我的$product_工件=$output->at('product_工件');
foreach my$variant(@{$data->{output}{product_artifacts}}){
$product_artifacts->append_内容($dom->new_标记('variant_name',$variant->{variant_name}));
$product_artifacts->append_content($dom->new_标记('artifacts');
my$artifacts=$product_artifacts->at('artifacts');
foreach my$artifact(@{$variant->{artifacts}){
foreach my$密钥(排序密钥%$工件){
$artifact->append_内容($dom->new_标记($key,$artifact->{$key}));
}
}
}
$root->append_content($dom->new_标记('message',$data->{message}));
my$xml=$dom->to_字符串;
这些示例都将XML作为字符生成;当输出到文件或其他文件时,应将其编码为UTF-8。请注意,XML::Simple已被弃用,作者本人建议使用其他模块。
但是,我不知道有一个模块可以用来轻松地将数据结构转储到XML中(除了XML::Dumper,但它有一个非常不同的输出结构),而无需“手动”构造数据结构
对于所需的输出格式,需要为XMLOut函数设置以下选项:
print XMLout($data,NoAttr => 1, RootName => 'root');
然而,这仍然会留下“message”标记,它是一个空数组,而XML::Simple似乎会悄悄地丢弃它(耶!)
XML::Simple很糟糕。它不一致,其文档不鼓励使用它。请不要因为没有人提供解决方案而提供解决方案。此解决方案不会对XML值进行转义。正确的解决方案是使用XML呈现器或XML模板器(我的建议是Text::Xslate或Mo)
<root>
<output>
<product_artifacts>
<artifacts>
<artifact_created>10-25-19 15:52:02</artifact_created>
<artifact_digital_size>123</artifact_digital_size>
<artifact_download_link>http://abc:rt/ </artifact_download_link>
<artifact_number>123/234</artifact_number>
<artifact_revision>AB1</artifact_revision>
</artifacts>
<variant_name>test_var</variant_name>
</product_artifacts>
</output>
<status>Success</status>
</root>
#!/app/perl/5.16.2/LMWP3/bin/perl
use strict;
use warnings;
binmode STDOUT, ":utf8";
use utf8;
use JSON;
use XML::Writer;
# Read input file in json format
my $json = qq(
{
"status": "Success",
"output": {
"product_artifacts": [
{
"variant_name": "test_var",
"artifacts": [
{
"artifact_created": "10-25-19 15:52:02",
"artifact_download_link": "http://abc:rt/ ",
"artifact_digital_size": 123,
"artifact_number": "123/234",
"artifact_revision": "AB1"
}
]
}
]
},
"message": []
}
);
my $data = decode_json($json);
my $writer = XML::Writer->new( OUTPUT => 'self',DATA_MODE => 1, DATA_INDENT => 4);
$writer->xmlDecl("UTF-8");
$writer->startTag('root');
$writer->dataElement(status => $data->{status});
$writer->startTag('output');
for my $p (@{$data->{output}{product_artifacts}}) {
$writer->startTag('product_artifacts');
$writer->dataElement($_ => $p->{$_}) for qw(variant_name);
for my $a (@{$p->{artifacts}}) {
$writer->startTag('artifacts');
$writer->dataElement($_ => $a->{$_}) for qw(artifact_created
artifact_download_link
artifact_digital_size
artifact_number
artifact_revision);
$writer->endTag('artifacts');
}
$writer->endTag('product_artifacts');
}
$writer->endTag('output');
$writer->emptyTag('message');
$writer->endTag('root');
print $writer->to_string();
print "\n";