我需要创建一个自定义XML文件,以便在我的Android应用程序中使用
该文件将包含我的应用程序中需要的一些自定义对象,
我知道我需要将它们放在res\xml
或res\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>
这可能吗?
请问我该如何实现?
答案 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允许您在更改某些文件时运行某些单元测试。当然,您的单元测试将成为单元测试回归的一部分。