用于将SGML转换为XML的正则表达式

时间:2017-08-31 05:33:29

标签: java regex xml sgml

我正在this链接的帮助下将sgml内容转换为xml内容。 使用sgmlString.replaceAll("<(([^<>]+?)>)([^<>]+?)(?=<(?!\\1))", "<$1$3</$2>");正则表达式,我几乎关闭了预期的结果,但对于以下文件,当有多个同名的并行标记没有关闭时,它只关闭最后一个标记的标记。

  

输入:

<SEC-HEADER>0001104659-17-052330.hdr.sgml : 20170817
    <ACCEPTANCE-DATETIME>20170817060417
    <ACCESSION-NUMBER>0001104659-17-052330
    <TYPE>8-K
    <PUBLIC-DOCUMENT-COUNT>4
    <PERIOD>20170816
    <ITEMS>7.01
    <ITEMS>8.16
    <FILING-DATE>20170817
    <DATE-OF-FILING-DATE-CHANGE>20170817
    <FILER>
        bye bye see you!
    </FILER>
</SEC-HEADER>
  

输出:(注意只有一个关闭的ITEMS标签和两个关闭的FILER,不是预期的)

  <SEC-HEADER>0001104659-17-052330.hdr.sgml : 20170817
     <ACCEPTANCE-DATETIME>20170817060417</ACCEPTANCE-DATETIME>
     <ACCESSION-NUMBER>0001104659-17-052330</ACCESSION-NUMBER>
     <TYPE>8-K</TYPE>
     <PUBLIC-DOCUMENT-COUNT>4</PUBLIC-DOCUMENT-COUNT>
     <PERIOD>20170816</PERIOD>
     <ITEMS>7.01<ITEMS>8.16</ITEMS>
     <FILING-DATE>20170817</FILING-DATE>
     <DATE-OF-FILING-DATE-CHANGE>20170817</DATE-OF-FILING-DATE-CHANGE>
     <FILER>bye bye see you!</FILER></FILER>
</SEC-HEADER>
  

预期:

  <SEC-HEADER>0001104659-17-052330.hdr.sgml : 20170817
         <ACCEPTANCE-DATETIME>20170817060417</ACCEPTANCE-DATETIME>
         <ACCESSION-NUMBER>0001104659-17-052330</ACCESSION-NUMBER>
         <TYPE>8-K</TYPE>
         <PUBLIC-DOCUMENT-COUNT>4</PUBLIC-DOCUMENT-COUNT>
         <PERIOD>20170816</PERIOD>
         <ITEMS>7.01</ITEMS>
         <ITEMS>8.16</ITEMS>
         <FILING-DATE>20170817</FILING-DATE>
         <DATE-OF-FILING-DATE-CHANGE>20170817</DATE-OF-FILING-DATE-CHANGE>
         <FILER>bye bye see you!</FILER>
    </SEC-HEADER>

我需要您对以下查询的善意建议/指导:

  1. 使用正则表达式获取结束标记以xml格式制作它是一种很好的方法,因为我读正则表达式很慢吗?
  2. 我要处理相当繁重的文件(最多18000行/标签),有没有更好的方法来实现它?
  3. 如何通过更改正则表达式来获得预期结果(我在EL中非常弱)

2 个答案:

答案 0 :(得分:1)

虽然它可能适用于手头的SGML,但通常使用regexp匹配/替换是将SGML转换为XML的一种可怕方法,因为SGML具有标记省略/标记推断,属性名称和值遗漏(如HTML中),以及SGML的XML配置文件中没有的其他简短形式和功能。

但是我可以完全推荐专用的osx SGML到XML转换程序。其来源可从http://openjade.sourceforge.net/获得。如果您使用的是Debian / Ubuntu,则可以通过sudo apt-get install opensp进行安装,如果您使用的是sudo port install opensp的Mac OS(使用必须首先安装的MacPorts)(不知道MacBrew)但是相当于。

答案 1 :(得分:0)

我在perl中有一个解决方案。 它基于<SEC-HEADER>的特殊处理,并将其纳入其中。

Perl代码:

use strict;
use warnings;

my $Input ='';
while(<>)
{
    $Input.=$_;
}

$Input =~ s/<((?!SEC-HEADER)([^\/<>]+?)>)([^<>]+?)(\s*?)(?=<[^\/])/<$1$3<\/$2>$4/g;
print $Input;

为了将其翻译成您的工具(我无法测试并且必须猜测其语法),我建议尝试:

sgmlString.replaceAll("<((?!SEC-HEADER)([^\/<>]+?)>)([^<>]+?)(\s*?)(?=<[^\/])", "<$1$3<\/$2>$4");

抱歉,您必须自己修改一些特定于工具的错误,可能是尝试和错误 使用我的perl版本,我得到了以下输出,我希望它足够接近,它只是不会占用<FILER>内的空白区域。

输出:

<SEC-HEADER>0001104659-17-052330.hdr.sgml : 20170817
    <ACCEPTANCE-DATETIME>20170817060417</ACCEPTANCE-DATETIME>
    <ACCESSION-NUMBER>0001104659-17-052330</ACCESSION-NUMBER>
    <TYPE>8-K</TYPE>
    <PUBLIC-DOCUMENT-COUNT>4</PUBLIC-DOCUMENT-COUNT>
    <PERIOD>20170816</PERIOD>
    <ITEMS>7.01</ITEMS>
    <ITEMS>8.16</ITEMS>
    <FILING-DATE>20170817</FILING-DATE>
    <DATE-OF-FILING-DATE-CHANGE>20170817</DATE-OF-FILING-DATE-CHANGE>
    <FILER>
        bye bye see you!
    </FILER>
</SEC-HEADER>

详细说明:

  • 使用与实际找到的代码名称匹配的否定匹配,而不是\1
  • /代替\
  • 一开始,期待非/
  • 忽略特殊标记名SEC-HEADER,因为您隐式允许
  • 捕获一些空格并使用它来缩小缩进和换行

如果你确实想要吃掉空格,这里有一个(perl)替换:

$Input =~ s/<(?!\/)([^<>]+)>\s*([^<>]+[^\s<>])\s*<\/\1>/<$1>$2<\/$1>/g;

您工具的猜测版本
(再次,抱歉小错误,请自己擦亮):

sgmlString.replaceAll("<(?!\/)([^<>]+)>\s*([^<>]+[^\s<>])\s*<\/\1>", "<$1>$2<\/$1>");

输出(在第一个代码后应用):

<SEC-HEADER>0001104659-17-052330.hdr.sgml : 20170817
    <ACCEPTANCE-DATETIME>20170817060417</ACCEPTANCE-DATETIME>
    <ACCESSION-NUMBER>0001104659-17-052330</ACCESSION-NUMBER>
    <TYPE>8-K</TYPE>
    <PUBLIC-DOCUMENT-COUNT>4</PUBLIC-DOCUMENT-COUNT>
    <PERIOD>20170816</PERIOD>
    <ITEMS>7.01</ITEMS>
    <ITEMS>8.16</ITEMS>
    <FILING-DATE>20170817</FILING-DATE>
    <DATE-OF-FILING-DATE-CHANGE>20170817</DATE-OF-FILING-DATE-CHANGE>
    <FILER>bye bye see you!</FILER>
</SEC-HEADER>