如何在XML文件中定义应用程序的验证规则

时间:2013-07-18 10:14:14

标签: python xml vb.net

我有一个应用程序可以根据某些设置规则验证CSV文件。应用程序检查CVS中的某些“列/字段”是否标记为必需,其他则检查其强制状态是否基于另一个字段。例如。第2列对第5列进行了条件检查,这样如果第5列有值,则第2列也必须有值。

我已经使用VB和Python实现了这一点。问题是这个逻辑在应用程序中是硬编码的。我想要的是将此规则移动到一个XML中,其中应用程序将读取该XML并处理该文件。如果处理更改的规则 - 并且它们经常更改 - 则应用程序保持不变,只有XML更改。

以下是python中的两个示例规则:

示例一

current_column_data = 5 #data from the current position in the CSV
if validate_data_type(current_column_data, expected_data_type) == False:
    return error_message
index_to_check_against = 10 #Column against which there is a "logical" test
text_to_check = get_text(index_to_check_against)
if validate_data_type(text_to_check, expected_data_type) == False:
    return error_message
if current_column_data > 10:    #This test could be checking String Vs String so have to keep in mind that to avoid errors since current column data could be a string value
    if text_to_check <= 0:
        return "Text to check should be greater than 0 if current column data is greater than 10 "

示例二

current_column_data = "Self Employed" #data from the current position in the CSV
if validate_data_type(current_column_data, expected_data_type) == False:
    return error_message
index_to_check_against = 10 #Column against which there is a "logical" test
text_to_check = get_text(index_to_check_against)
if validate_data_type(text_to_check, expected_data_type) == False:
    return error_message
if text_to_check == "A":    #Here we expect if A is provided in the index to check, then current column should have a value hence we raise an error message
    if len(current_column_data) = 0:
        return "Current column is mandatory given that "A" is provided in Column_to_check""

注意:对于CSV中的每一列,我们已经知道了预期的数据类型,该字段的预期长度,是否为强制,可选或条件,以及其条件是否为其他列条件基于

现在我需要一些关于如何在XML中执行此操作的指导,并且应用程序读取XML并知道如何处理每个列。

有人在其他地方提出了以下示例,但我仍然无法理解这个概念。:

<check left="" right="9" operation="GTE" value="3" error_message="logical failure for something" /> 
#Meaning: Column 9 should be "GTE" i.e. Greater than or equal two value 3"

有没有不同的方法来实现这种逻辑,甚至是改善我在这里的方式?

建议和指示欢迎

2 个答案:

答案 0 :(得分:2)

此概念称为域特定语言(DSL) - 您正在有效地创建用于验证CSV文件的迷你编程语言。您的DSL允许您明确简洁有效CSV文件的规则。

这个DSL可以用XML表示,或者另一种方法是在python中开发一个函数库。然后你的DSL可以表示为一个mini-python程序,它是这些函数的序列。这种方法被称为语言或“内部”DSL - 并且有一个好处,即您可以在您的语言中使用python的全部功能。

看着你的样品 - 你已经非常接近这个了。当我阅读它们时,它们几乎就像是CSV验证规则的英文描述。

不要觉得你必须遵循XML路线 - 在Python中保存所有内容没有任何问题

  • 您可以拆分代码,因此您有一个python文件,其中包含您在DSL中表达的“CSV验证规则”,您需要经常更新/重新分发,以及单独定义DSL功能的文件,这些文件的更改频率会降低
  • 在某些情况下,甚至可以将DSL开发到非程序员可以更新/维护其中编写的“程序”的程度

答案 1 :(得分:0)

您要解决的问题不一定与XML有关。好的,您可以使用XSD对XML进行验证,但这意味着您的数据需要是XML,并且我不确定您是否可以执行此操作以扩展“如果A&gt; 3,遵循规则适用”。

稍微不那么优雅,但可能比Ross答案更简单的方法,只是将规则集定义为 data 并具有特定的功能处理它们,这基本上是您的XML示例所做的,存储(即使用XML序列化数据---但您可以使用任何其他序列化格式,如JSON,YAML,INI甚至CSV(不建议使用它)。

因此,您可以专注于规则的数据模型。我将尝试使用XML(但不使用属性)来说明:

<cond name="some explanatory name">
    <if><expr>...</expr>
    <and>
        <expr>
            <left><column>9</column></left>
            <op>ge</op>
            <right>3</right>
        </expr>
        <expr>
            <left><column>1</column></left>
            <op>true</op>
            <right></right>
        </expr>
    </and>
</cond>

然后,您可以将其加载到Python并遍历每行,并在适当的时候提出一个很好的解释异常。

编辑:您提到该文件可能需要是人类可写的。请注意,YAML是专为此而设计的。

类似(不一样,改为使其更好地说明语言)结构:

# comments, explanations...
conds:
    -   name: some explanatory name
        # seen that? no quotes needed (unless you include some of
        # quite limited set of special chars)
        if:
            expr:
                # "..."
            and:
                expr:
                    left:
                            column: 9
                    op:     ge
                    right:  3
                expr:
                    left:
                            column: 1
                    op:     true
    -   name: some other explanatory name
        # i'm using alternative notation for columns below just to have
        # them better indented (not sure about support in libs)
        if:
            expr:
                # "..."
            and:
                expr:
                    left:   { column: 9 }
                    op:     ge
                    right:  3
                expr:
                    left:   { column: 1 }
                    op:     true