我一直在使用 XSOM 解析器 (xsom-20140925.jar) 来解析 XSD 1.0 并能够解析所有 xs:elements 和限制(如模式、minOccurs 等)。
最近我们的 XSD1.0 升级到了 XSD1.1 版本,其中包含了新的断言标签。我的 XSOM 解析器无法识别此断言标记并引发以下异常。
无法解析输入流:org.xml.sax.SAXParseException:意外<xsd:assert>
出现在行。java.lang.NullPointerException
基本上我的需要是将 XSD 中的所有限制自动化到 JavaScript 函数,以便可以验证客户端 UI。
我已经完成了谷歌搜索并了解 Xerces-j 只能针对 XSD1.1 验证 XML。
但我的要求是解析断言值并转换为 JavaScript 函数。
考虑下面的断言示例:这里我需要解析双引号“”之间的值,并根据条件到达一个 JavaScript 函数。
xsd:assert test="(exists(companyName) and companyTier='TierOne')"
有没有办法实现上述要求?任何帮助或建议都会对我有很大帮助。
..................................................... ......................
感谢您的回答。通过关闭 sax 验证,我可以解析断言标记值。但我的要求是将这些作为 XSD1.1 功能的断言值(如下所示)转换为 Java 正则表达式或任何可以评估的表达式,并且我应该具有正确的链接,即该断言标记所属的元素。
我了解 xercesImpl-xsd11-2.12-beta 具有可以使用的 Xpath2.0 处理器。但是我无法将 XSD 解析为带有 assert 标签的 XSModel。
使用的 XSD 文件:
<?xml version="1.1" encoding="UTF-8"?>
<schema targetNamespace="http://www.example.org/Example" elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/Example">
<element name="Node" type="tns:NodeType"></element>
<complexType name="NodeType">
<sequence>
<element name="Node" type="tns:NodeType"
maxOccurs="unbounded" minOccurs="0">
</element>
</sequence>
<attribute name="partnumber">
<simpleType>
<restriction base="string">
<pattern value="[A-Z0-9_\-]+"></pattern>
</restriction>
</simpleType>
</attribute>
<assert test="starts-with(@partnumber,../@partnumber)"/>
</complexType>
</schema>
要解析的 Java 代码:
System.setProperty(DOMImplementationRegistry.PROPERTY, "org.apache.xerces.dom.DOMXSImplementationSourceImpl");
DOMImplementationRegistry registry;
XSNamedMap xsMap;
try {
registry = DOMImplementationRegistry.newInstance();
XSImplementationImpl impl = (XSImplementationImpl) registry.getDOMImplementation("XS-Loader");
XSLoader schemaLoader = impl.createXSLoader(null);
XSModel model = schemaLoader.loadURI("testxsdassert.xsd");
}
执行时控制台中显示以下错误:[Error] testxsdassert.xsd:17:65: s4s-elt-invalid-content.1: 'NodeType' 的内容无效。元素 'assert' 无效、放错位置或过于频繁地出现。
任何线索或建议都会帮助我。
谢谢。
..................................................... .........................................
很抱歉没有明确要求。让我再试一次。
- 现有的 XSOM 解析器(参见下面的代码)将解析任何 XSD 并针对 XSD 中存在的任何元素检索所有限制,例如 MINLENGTH、MAXLENGTH、PATTERN、ENUMERATION。这个解析器的意图是仅仅解析这些值并根据它的元素名称进行存储。对于以下示例(parser.xsd),此结构派生-> {allowedMonths,["JAN","FEB"]}
解析后,我会将解析后的结构 {allowedMonths,["JAN","FEB"]} 转换为 JavaScript 函数,在 UI 验证中调用此函数以检查用户输入的值是否动态符合 XSD。
到目前为止,这一切都很好。这个解决方案是自动化的,这样在 XSD 中的任何新添加时,这个解析器都会处理 JS 代码的生成。
**Parser.xsd**
<xsd: simpleType name="allowedMonths">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="JAN"/>
<xsd:enumeration value="FEB"/>
</xsd:restriction>
</xsd:simpleType>
**Parser.java**
XSOMParser parser;
parser.parse(xml);
XSSchemaSet schemaSet = null;
try {
schemaSet = parser.getResult();
} catch (SAXException ex) {
System.out.println("Could not parse: " + ex);
}
Iterator <XSElementDecl> itre = schemaSet.iterateElementDecls();
while(itre.hasNext()) {
XSElementDecl xse = (XSElementDecl) itre.next();
hmReturned.put(xse.getName(), hm);
XSComplexType xscomp = xse.getType().asComplexType();
if (xscomp != null) {
XSContentType xscont = xscomp.getContentType();
XSParticle particle = xscont.asParticle();
getElementsRecursively(hm, particle);
}
}
private void getElementsRecursively(HashMap<String, Object> hm, XSParticle xsp) {
if(xsp != null){
XSTerm term = xsp.getTerm();
if(term.isElementDecl()) {
XSComplexType xscmp = (term.asElementDecl()).getType().asComplexType();
//---
if (xscmp == null){
MappingXSDJSElement mapElementObj = new MappingXSDJSElement();
//public List<String> enumeration = new ArrayList<String>();
if(xsp.getTerm().asElementDecl().getType().asSimpleType() != null)
{
if(xsp.getTerm().asElementDecl().getType().asSimpleType().isRestriction())
{
XSRestrictionSimpleType restriction=xsp.getTerm().asElementDecl().getType().asSimpleType().asRestriction();
if(restriction != null){
List<String> enumeration = new ArrayList<String>();
Iterator<? extends XSFacet> i = restriction.getDeclaredFacets().iterator();
while(i.hasNext()){
XSFacet facet = i.next();
if(facet.getName().equals(XSFacet.FACET_MAXLENGTH)){
mapElementObj.setMaxLength(facet.getValue().value);
}
if(facet.getName().equals(XSFacet.FACET_MINLENGTH)){
mapElementObj.setMinLength(facet.getValue().value);
}
if(facet.getName().equals(XSFacet.FACET_PATTERN)){
mapElementObj.setPattern(facet.getValue().value);
}
if(facet.getName().equals(XSFacet.FACET_ENUMERATION)){
enumeration.add(facet.getValue().value);
mapElementObj.setEnumeration(enumeration);
// System.out.println(enumeration.toString());
}
}
}
}
}
if(xsp.getMinOccurs().intValue() == 0)
{
// hm.put(term.asElementDecl().getName(), "|");
mapElementObj.setMinOccurs("0");
}
else if(xsp.getMinOccurs().intValue() == 1)
{
// hm.put(term.asElementDecl().getName(), "=");
mapElementObj.setMinOccurs("1");
}
hm.put(term.asElementDecl().getName(), mapElementObj);
} else{
XSContentType xscont = xscmp.getContentType();
XSParticle particle = xscont.asParticle();
HashMap<String, Object> newHm = new HashMap<String, Object>();
getElementsRecursively(newHm, particle);
hm.put(term.asElementDecl().getName(), newHm);
}
//---
} else if(term.isModelGroup()){
XSModelGroup model = term.asModelGroup();
XSParticle[] parr = model.getChildren();
for(XSParticle partemp : parr ){
getElementsRecursively(hm, partemp);
}
}
}
}
- 要求:现在 XSD 已得到增强,包括具有跨字段验证。所以最终我不得不增强我的解析器来为每个元素捕获这些断言,并为 XSD 的每个元素提供 JavaScript 函数。所以我需要找到一种方法来解析这些存在于任何简单和复杂类型元素中的断言值。
您将解析为原始类型 XML 的建议似乎不适合我现有的 XSOM 解析器。即我正在寻找解析器 API 来获取标记的值,因此该解决方案对任何 XSD 都是通用的。
有关此方法的任何建议都将有助于解决问题。