【问题标题】:How can I determine if a given DTD a subset of another?如何确定给定 DTD 是否是另一个 DTD 的子集?
【发布时间】:2015-02-10 21:57:21
【问题描述】:

我需要验证“简化”DTD 是否真的是更大 DTD 的子集,即根据“简化”DTD 有效的文档也将始终根据较大(或“主”)DTD 有效。

现在正在编写简化的 DTD - 它是从主 DTD 派生的(如果反过来,可以简单地将较小的 DTD 包含到较大的 DTD 中)。

如何确定简化 DTD 是否源自主 DTD?

【问题讨论】:

    标签: xml diff dtd


    【解决方案1】:

    DTD 实际上只是伪装的上下文无关语法。一个文法 G 表示一组可能的合法字符串,这些字符串组成了该文法所代表的未陈述语言 L(G)。

    你问的,等于判断你有没有G1和G2,L(G1)是不是L(G2)的一个子集。我的语言理论越来越生疏了,我不记得这是否是可计算的,但我猜这真的很难,因为你必须证明 G1 中的任意推导总是在 G2 中具有推导。

    您也许可以回答 G1 的结构是否可以通过证明 G1 的每个元素与G2,本质上是通过显示每个语法规则 在 G1 中有一个相应的规则在 G2 中删除了元素。您对 DTD 进行差异化的想法似乎是沿着这条线走的,但前提是如果差异很大,您会遇到一般问题而不是更简单的问题。至少您描述问题的方式(G2源自主DTD)我认为您有机会。 diff 的目的是通过找到最小的差异来识别兼容的规则。

    如果你有语法规则 g2 = A ;另一个你声称相关的 g1 = A 和 你想检查的, 您首先必须证明 A 在 G1 中派生的字符串标记是超集 在 G2 中派生的记号 A 的字符串。这看起来就像比较两种语言的原始无约束问题;我们现在只是比较两条规则 g1 和 g2 的子语言。

    所以现在我认为你必须坚持 g1 可达的每个子规则在结构上与 g2 中的相应子规则兼容,以使其实用。 我认为您可能可以编写一个递归过程来检查这一点。此过程最需要帮助的是您在 LALR 解析器生成器中往往会找到的所有集合运算符(FirstOf、..)。

    在另一个方面,我的公司制造了Smart Differencer 工具,它根据语言元素和对这些元素的编辑操作计算语言结构的增量。它由语言定义参数化。 SmartDifference 目前适用于各种传统语言(C、C++、C#、COBOL、Java、PHP、Python ......)。 XML(和 DTD)也是一种语言,我们有一个语言定义,并且我们已经构建了一个实验性的 XML Smart Differencer 工具。它应该可以在 DTD 上正常工作。如果您有进一步的直接兴趣,请离线联系我(参见简历)。

    编辑:只是为了笑,我尝试了以下两个 DTD,一个来自另一个:

    orderform.xml

    <?xml version='1.0' ?>
    <!DOCTYPE orderform [
    
    <!ELEMENT orderform (name,company,address,items) >
    <!ELEMENT name ( firstname, lastname )>
    <!ELEMENT firstname ( #PCDATA )>
    <!ELEMENT lastname ( #PCDATA )>
    <!ELEMENT company ( #PCDATA )>
    <!ELEMENT address ( street, city, country )>
    <!ELEMENT street ( #PCDATA )>
    <!ELEMENT city( #PCDATA )>
    <!ELEMENT country ( zipcode | nation )>
    <!ELEMENT zipcode ( #PCDATA )>
    <!ELEMENT nation ( #PCDATA )>
    <!ELEMENT items (item)+ >
    <!ELEMENT item ( partnumber, quantity, unitprice)>
    <!ELEMENT partnumber ( #PCDATA )>
    <!ELEMENT quantity ( #PCDATA )>
    <!ELEMENT unitprice  ( #PCDATA )>
    ]>
    
    <done/>
    

    orderform2.xml

    <?xml version='1.0' ?>
    <!DOCTYPE orderform [
    
    <!ELEMENT orderform (name,company,location,item) >
    <!ELEMENT name ( firstname, lastname )>
    <!ELEMENT firstname ( #PCDATA )>
    <!ELEMENT lastname ( #PCDATA )>
    <!ELEMENT company ( #PCDATA )>
    <!ELEMENT location ( street, city, country )>
    <!ELEMENT street ( #PCDATA )>
    <!ELEMENT city( #PCDATA )>
    <!ELEMENT country ( zipcode | nation )>
    <!ELEMENT zipcode ( #PCDATA )>
    <!ELEMENT nation ( #PCDATA )>
    <!ELEMENT item ( partnumber, unitprice)>
    <!ELEMENT partnumber ( #PCDATA )>
    <!ELEMENT quantity ( #PCDATA )>
    <!ELEMENT unitprice  ( #PCDATA )>
    ]>
    
    <done/>
    

    [先看看你是否能自己发现差异:-)

    然后运行 ​​XML SmartDifferencer:

    C:\DMS\Domains\XML\Analyzers\SmartDifferencer\Source>DMSSmartDifferencer XML -SuppressSourceCodeForRenamings C:\DMS\Domains\XML\Tool
    s\DTD2COBOL\orderform.xml C:\DMS\Domains\XML\Tools\DTD2COBOL\orderform2.xml
    Copyright (C) 2009 Semantic Designs; All Rights Reserved
    XML SmartDifferencer Version 1.1.1
    Copyright (C) 2009 Semantic Designs, Inc; All Rights Reserved; SD Confidential
    Powered by DMS (R) Software Reengineering Toolkit
    *** Unregistered SmartDifferencer Version 1.1
    *** Operating with evaluation limits.
    
    *** Parsing file C:/DMS/Domains/XML/Tools/DTD2COBOL/orderform.xml ...
    *** Parsing file C:/DMS/Domains/XML/Tools/DTD2COBOL/orderform2.xml ...
    *** Creating suffix tree ...
    *** Determining maximal pairs ...
    *** Sorting maximal pairs ...
    *** Determining differences ...
    *** Printing edits ...
    Rename 4.1-9.44 to 4.1-9.45 with 'address'->'location' and 'items'~>'item'
    Delete 15.1-15.25 merging 15.18-15.21 into 4.44-4.47
    <<!ELEMENT items (item)+ >
    Delete 16.30-16.38 merging 16.30-16.38 into 15.18-15.28 with 'quantity'~>'partnumber'
    <                             quantity,
    

    是的,这就是我为得到派生的所做的。 (符号 N.M 的意思是“第 N 行,第 M 列”)。

    【讨论】:

    • 非常感谢您的详细回答;我有一种感觉,一般来说,我所追求的要么非常困难,要么不可能。但是,由于我们现在正在编写较小的 DTD,因此最好的方法可能是格外小心(即“手动”)。然后我们将通过两个 DTD 运行文档;如果它们匹配“较小”的而不是“较大”的,那么就出了问题……沿着这条线可能有一种“蛮力”方法:生成许多随机的文档实例来验证小 DTD 并运行它们大一点的,看看好不好用?我也很高兴了解 Smart Differencer!谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多