如何使用 Schematron 评估 SOAP 响应?
How to evaluate SOAP response using Schematron?
我在下面有一个 SOAP 响应
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:getCountryResponse xmlns:ns2="http://spring.io/guides/gs-producing-web-service">
<ns2:country>
<ns2:name>Spain</ns2:name>
<ns2:population>46704314</ns2:population>
<ns2:capital>Madrid</ns2:capital>
<ns2:currency>EUR</ns2:currency>
</ns2:country>
</ns2:getCountryResponse>
</SOAP-ENV:Body>
和一个 Schematron 文件,我希望在我 运行 验证时吐出一个错误,因为 Header 元素没有名为 'foo'
的属性
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<sch:ns uri="http://www.w3.org/2003/05/soap-envelope" prefix="SOAP-ENV"/>
<sch:pattern id="structure">
<sch:rule context="SOAP-ENV:Header">
<sch:assert test="@foo">The element Header must have an attribute named foo.</sch:assert>
</sch:rule>
</sch:pattern>
但我没有失败。我错了什么?我用于验证的代码是
internal class SchematronValidatorUtil {
companion object {
@JvmStatic
fun isXmlStringValidAgainstSchema(schema: String, xml: String,
charset: Charset = StandardCharsets.UTF_8): SchematronResult {
val schematronResource = SchematronResourcePure.fromString(schema, charset)
val input = StreamSource(ByteArrayInputStream(xml.toByteArray(charset)))
val schematronOutput = schematronResource.applySchematronValidationToSVRL(input)
val failures = mutableListOf<String>()
return schematronOutput?.let { schemaOutput ->
schemaOutput.activePatternAndFiredRuleAndFailedAssert
.map { each -> each as? FailedAssert }
.forEach { each -> each?.let { value ->
failures.add(String.format("%s: %s", value.test, value.text)) } }
val type = if (failures.any())
SchematronResultType.XmlDoesNotMatchSchema else SchematronResultType.XmlMatchesSchema
return SchematronResult(type, failures)
} ?: SchematronResult(SchematronResultType.InvalidSchematronFile, failures)
}
}
}
SOAP 信封将 SOAP-ENV 名称空间前缀声明为 http://schemas.xmlsoap.org/soap/envelope/
Schematron 模式将 SOAP-ENV 命名空间前缀声明为 http://www.w3.org/2003/05/soap-envelope
更改 Schematron 架构中的 ns
声明以匹配 SOAP 信封中声明的名称空间 URI,它应该可以工作。
(测试此类问题的一种有用方法是临时将规则上下文更改为 *:Header
,这将匹配任何命名空间中的 Header
元素。如果架构适用于该更改,那么您已将问题缩小为命名空间问题。)
我在下面有一个 SOAP 响应
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:getCountryResponse xmlns:ns2="http://spring.io/guides/gs-producing-web-service">
<ns2:country>
<ns2:name>Spain</ns2:name>
<ns2:population>46704314</ns2:population>
<ns2:capital>Madrid</ns2:capital>
<ns2:currency>EUR</ns2:currency>
</ns2:country>
</ns2:getCountryResponse>
</SOAP-ENV:Body>
和一个 Schematron 文件,我希望在我 运行 验证时吐出一个错误,因为 Header 元素没有名为 'foo'
的属性<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<sch:ns uri="http://www.w3.org/2003/05/soap-envelope" prefix="SOAP-ENV"/>
<sch:pattern id="structure">
<sch:rule context="SOAP-ENV:Header">
<sch:assert test="@foo">The element Header must have an attribute named foo.</sch:assert>
</sch:rule>
</sch:pattern>
但我没有失败。我错了什么?我用于验证的代码是
internal class SchematronValidatorUtil {
companion object {
@JvmStatic
fun isXmlStringValidAgainstSchema(schema: String, xml: String,
charset: Charset = StandardCharsets.UTF_8): SchematronResult {
val schematronResource = SchematronResourcePure.fromString(schema, charset)
val input = StreamSource(ByteArrayInputStream(xml.toByteArray(charset)))
val schematronOutput = schematronResource.applySchematronValidationToSVRL(input)
val failures = mutableListOf<String>()
return schematronOutput?.let { schemaOutput ->
schemaOutput.activePatternAndFiredRuleAndFailedAssert
.map { each -> each as? FailedAssert }
.forEach { each -> each?.let { value ->
failures.add(String.format("%s: %s", value.test, value.text)) } }
val type = if (failures.any())
SchematronResultType.XmlDoesNotMatchSchema else SchematronResultType.XmlMatchesSchema
return SchematronResult(type, failures)
} ?: SchematronResult(SchematronResultType.InvalidSchematronFile, failures)
}
}
}
SOAP 信封将 SOAP-ENV 名称空间前缀声明为 http://schemas.xmlsoap.org/soap/envelope/
Schematron 模式将 SOAP-ENV 命名空间前缀声明为 http://www.w3.org/2003/05/soap-envelope
更改 Schematron 架构中的 ns
声明以匹配 SOAP 信封中声明的名称空间 URI,它应该可以工作。
(测试此类问题的一种有用方法是临时将规则上下文更改为 *:Header
,这将匹配任何命名空间中的 Header
元素。如果架构适用于该更改,那么您已将问题缩小为命名空间问题。)