我在将不完整的 XML 文件格式化为正确标记的 XML 时遇到问题,以便我可以轻松地从中获取标记内的 XML 值。
输出的文本如下:
Input parameters
User : abcd
User : abc@1234
User Agent : pqr Server/12.0/1.0
file Name : tmpfile.9133
Timeout : 5
Nr thread : 1
Nr resends : 1
_____ Adresses:____
http://localhost:12345/Mrr
File tmpfile.9133 Contains 1 requests.
start thread 0
---------------- Sending --------------------
<methodCall>
<methodName>Test1</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>row1</name>
<value>
<i4>1</i4>
</value>
</member>
<member>
<name>main1</name>
<value>ADM</value>
</member>
<member>
<name>originTransactionID</name>
<value>464372231</value>
</member>
<member>
<name>min</name>
<value>99912345678</value>
</member>
<member>
<name>originTimeStamp</name>
<value>
<dateTime.iso8601>20150929T02:20:32+0300</dateTime.iso8601>
</value>
</member>
<member>
<name>main2</name>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>ID</name>
<value>
<i4>115001</i4>
</value>
</member>
<member>
<name>ValueNew</name>
<value>
<string>0</string>
</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</member>
<member>
<name>originHostName</name>
<value>rat</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
---------------- Recived --------------------
HTTP/1.1 200 OK
X-Powered-By: abc
Date: Mon, 28 Sep 2015 23:20:32 GMT
Server: xyz
Set-Cookie: JSESSIONID=15du5xtimqk42qoeej6o8l0u6;Path=/
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Length: 1489
Content-Type: text/xml
<?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value><struct><member><name>fsdfsdfsdf</name><value><array><data><value><i4>536871492</i4></value></data></array></value></member><member><name>sdfsdfsdf</name><value><array><data><value><i4>0</i4></value></data></array></value></member><member><name>txnID</name><value><string>464372231</string></value></member><member><name>responseCode</name><value><i4>0</i4></value></member><member><name>info</name><value><array><data><value><struct><member><name>ID</name><value><i4>115001</i4></value></member><member><name>Value</name><value><string>0</string></value></member><member><name>Information</name><value><array><data><value><struct><member><name>ID</name><value><i4>11500101</i4></value></member><member><name>TSource</name><value><i4>3</i4></value></member><member><name>TValue</name><value><string>524288000</string></value></member></struct></value><value><struct><member><name>TID</name><value><i4>11500102</i4></value></member><member><name>TSource</name><value><i4>3</i4></value></member><member><name>TValue</name><value><string>519045120</string></value></member></struct></value></data></array></value></member></struct></value></data></array></value></member></struct></value></param></params></methodResponse>
----------------------------------------------
现在我想执行2个操作:
使这个输出从标记
---------------- Recived --------------------
到结束被修剪,并将其存储在一个单独的变量中。然后修剪该文件,使其成为具有正确标签和所有内容的完美 XML 文件...即从
<?xml version="1.0" encoding="UTF-8"?>
到开始</methodResponse>
。
我只想在 Solaris 服务器上执行上述两项任务。我尝试使用xmllint --xpath
但似乎 xpath 不在包中。所以请建议任何其他方式。
答案1
官方的回答是——你不知道。损坏的 XML 从设计上来说是致命的。任何解析器修复根据定义,损坏的 XML 也不是 XML 解析器。
您应该拒绝 XML 并告诉“上游”他们的数据已损坏 - 因为确实如此。非常努力地推动这一点,因为转发修复 XML 的黑客行为对于代码的长期稳定性和可靠性来说是非常糟糕的消息。它可能有一天会随机损坏。
话虽如此,您的 XML 并没有被破坏,它只是被封装在一个文本文件中。它缺少诸如声明之类的东西,但这实际上并不是正式要求的。
所以你可以这样做:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $xml;
while ( <> ) {
if ( m/-- Sending --/ .. /-- Recived --/ ) {
next if m/----/; ##skip the sending/recived lines
next if m/^\s*$/; #skip any blank lines
$xml .= $_; #add the current line to "$xml".
}
}
my $twig = XML::Twig -> new ( 'pretty_print' => 'indented_a' )
$twig -> parse ( $xml );
$twig -> set_encoding('utf-8');
$twig -> set_xml_version('1.0');
$twig -> print;
你将要需要一个 XML 库 - 我使用它是XML::Twig
因为它广泛可用,并且在某些情况下默认安装/可以通过包管理器使用。 (如果没有的话,您应该能够从 CPAN 获取它)。
但实际上您并不需要它 - 它将print $xml
为您提供有效的 XML,然后您可以将其与您要使用的任何工具一起使用。
这 - 鉴于您的源数据如上 - 吐出:
<?xml version="1.0" encoding="utf-8"?>
<methodCall>
<methodName>Test1</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>row1</name>
<value>
<i4>1</i4>
</value>
</member>
<member>
<name>main1</name>
<value>ADM</value>
</member>
<member>
<name>originTransactionID</name>
<value>464372231</value>
</member>
<member>
<name>min</name>
<value>99912345678</value>
</member>
<member>
<name>originTimeStamp</name>
<value>
<dateTime.iso8601>20150929T02:20:32+0300</dateTime.iso8601>
</value>
</member>
<member>
<name>main2</name>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>ID</name>
<value>
<i4>115001</i4>
</value>
</member>
<member>
<name>ValueNew</name>
<value>
<string>0</string>
</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</member>
<member>
<name>originHostName</name>
<value>rat</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>