2017-10-04 98 views

回答

3

一个DTD反对,你可以验证文档这个在线工具可以很容易地产生:

<!ELEMENT e (#PCDATA | e)* > 

或者对XSD,仅包含一个架构文档

<xsd:element name="e"/> 

如果这样做不能令人满意,也许你忘了说你想让DTD接受你的XML文档有效。在这种情况下,我会实施类似下面的伪代码,在XSLT或XQuery

for each $gi in distinct-values($input/descendant-or-self::*/name()) 
return '<!ELEMENT ' || $gi || ' ANY >&#xA;' 

对于XSD,改变return语句

return '<xsd:element name="{$gi}"/>' 

如果这些都不能让人满意,或许你忘了说文档语法应该服从哪些其他限制。

我们可以生成一个捕获输入中父/子关系的语法(即它允许任何元素E成为元素F的子元素,当且仅当某个E元素作为F的子元素出现在输入中元素),代码如

for each $gi in distinct-values($input/descendant-or-self::*/name()) 
let $occurrences := $input/descendant-or-self::*[name() = $gi] 
    $children := distinct-values($occurrences/*/name(), 
    $mixed := some $t in $occurrences/child::text() 
       satisfies normalize-space($t), 
    $contentmodel0 := string-join(
         (if ($mixed) then '#PCDATA' else(), $children), 
         ' | ' 
        ) 
return '<!ELEMENT ' || $gi || ' ' 
     || '(' 
     || $contentmodel0 
     || ')* >&#xA;' 

我将为读者留下相应的XSD公式作为练习。

如果语法不足以捕获输入中的父/子关系,但是您还希望允许语法中任何元素的子元素序列在某种程度上匹配输入中的示例,那么你已经达到了一个有趣的问题(值得硕士论文或不久前的论文):对于你输入中的元素E的每个实例,你有一些有限数量的子代序列:你的任务是定义一个常规语言,包括那些序列并清楚地捕捉输入的隐含模式。很明显,很大程度上取决于你对“喜欢”和“明确”的定义。

如果你的要求是,孩子的序列中的语法被允许当且仅当它在输入实例,那么元素E的内容模型的制定是简单的,复杂的DTD和XSD只能由确定性规则(在XSD中被称为'独特的粒子属性规则',这只是一种稍微不太清楚和更强烈的说'决定论规则'的方式)。对于任何给定的序列集合,可能有不止一种可能的公式作为内容模型;选择最简单的内容模型需要一定程度的复杂性,以及找到最简单的可用公式的方法。

如果你做了这个实验的样本HTML文档,你可能会发现,ul因为输入了两个列表,一个有四个项目和一个九结束了与像(li, li, li, li, (li, li, li, li, li)?)内容模型。如果您希望程序为列表生成“更简单”或“更好”的内容模型,如(li+)(li*),那么您希望语法不仅允许在输入中找到的有限数量的序列子代,而且还允许其他序列“like “他们。也就是说,你必须找到一种合适的方法来从投入中进行概括。有无数种方式可以这样做(甚至当法律概括的类别被严格限制为任何人现在知道该怎么做时,仍然有非常多的数字),并且选择那种感觉“正确”的一个人对于大多数软件来说可能很难。

总之:有文件的语法,将接受您的XML输入为有效无穷多个。如果他们对你的目的并不完全相同,那么你需要更紧密地约束你的问题,以便它有一个有用的答案。

更多信息this earlier Stack Overflow question,而如果你有寻找答案的网站上张贴你的问题之前,您应该已是可用的。

+0

感谢您的详细解释@C。 M. Sperberg-McQueen。我只是在寻找一个简单的在线工具。如xml.mherman.org。 – Varun

+0

+1用于显示如何在单词的两个意义上生成语法*而不是**输入**所有*,这是OP请求的。 :-) – kjhughes

相关问题