Android:在编译时验证xml文件?

时间:2016-01-05 12:43:06

标签: java android xml

我需要创建一个自定义XML文件,以便在我的Android应用程序中使用

该文件将包含我的应用程序中需要的一些自定义对象,

我知道我需要将它们放在res\xmlres\raw中。行。

现在,如果XLM出现问题,我希望在编译时得到通知:

例如:

假设我想通过XML定义猫:

<cats>
    <siamese-cat
        fur="short"
        tail="5" />

    <persian-cat
        fur="short"
        tail="5" />
</cats>

我想知道如果我做这样的事情,是否有可能得到编译时警告:

(吠叫不是我已经定义的猫可以做的事情):

 <cats>
    <persian-cat
        barks="true"
        fur="short"
        tail="5" />
</cats>

这可能吗?

请问我该如何实现?

3 个答案:

答案 0 :(得分:5)

以下内容适用于gradle构建系统。

首先,定义一个Xml Schema(XSD)文档,该文档准确指定XML文档的结构。例如,在文件test.xsd中:

<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
    <xs:element name="animals">
        <xs:complexType>
            <xs:sequence minOccurs="0">
                <xs:element name="animal">
                    <xs:complexType>
                        <xs:attribute name="name" type="xs:string"/>
                        <xs:attribute name="age" type="xs:int"/>
                        <xs:attribute name="sound" type="xs:string"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

在上面的示例中,XSD文档指定我们只能有<animal>个标签,只有3个属性:名称,年龄和声音。此外,还严格定义了这些属性的数据类型。如果您不熟悉XML模式,可以阅读一些online documentation

接下来,通过引用text.xsd作为其架构,创建一个应该遵循上述架构的XML文档。例如,在文件test.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<animals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation='test.xsd'>
    <animal name="kitty" age="2" sound="meow"/>
    <cat name="bad_cat"></cat>
</animals>

正如您所看到的,我们故意添加了一个标记<cat>,它在我们刚刚定义的模式定义中没有。

  

如果您使用的是Android Studio,它会自动查找   模式文件并提供自动完成以及突出显示模式   编辑XML文件时出错。

但是每次Gradle构建android项目时,目的都是使用XSD架构验证XML文档。因此,我们定义了一个自定义Gradle任务来执行此操作。例如,在build.gradle

import javax.xml.XMLConstants
import javax.xml.transform.stream.StreamSource
import javax.xml.validation.SchemaFactory

task validateXml {
    File xml = new File('./test.xml');
    File xsd = new File('./test.xsd');

    def factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    def schema = factory.newSchema(xsd);
    def validator = schema.newValidator();
    validator.validate(new StreamSource(xml));
}

这里我们使用Java XML API编写一些groovy代码来读取这两个文件并使用XSD文件验证XML文件。您现在可以从Gradle CLI运行此任务:

例如:

./gradlew validateXml

它将失败,错误:

A problem occurred evaluating root project 'Bad Cats'.
> cvc-complex-type.2.4.d: Invalid content was found starting with element 'cat'. No child element is expected at this point.

大。现在我们希望validateXml任务在项目构建的每个时间运行。更具体地说,当打包文件时。因此,我们在Gradle构建文件中添加了一行(在定义validateXml任务之后):

assemble.dependsOn validateXml;

现在,assemble任务会在构建时自动调用validateXml

将来,您只需更新XSD文件即可为XML文件应用新规则。

答案 1 :(得分:1)

Android Lint自定义救援规则。您可以按照here所述创建自定义lint规则,并在每次构建之前运行检查。如果您的自定义XML文件出现问题 - 您将在控制台中收到通知。

答案 2 :(得分:1)

建议:转向单元测试。

您可以创建检查XML完整性的生产代码(例如,通过运行解析器;包括模式验证);那么你只需在某些单元测试中运行该代码。 (显然它有点复杂;你必须仔细研究对你来说最有意义的东西;但是,我们做了类似的事情;结果证明它非常有帮助。)

不完全是“编译时间”,而是关闭 - 因为许多IDE允许您在更改某些文件时运行某些单元测试。当然,您的单元测试将成为单元测试回归的一部分。