如何解析 XSD1.1 功能,准确地说是 <xs:assert> 标签?
How to parse XSD1.1 features, precisely <xs:assert> tag?
我一直在使用 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 中的所有限制自动化到 Java 脚本函数,以便客户端 UI 可以被验证。
我进行了谷歌搜索,了解到 Xerces-j 只能针对 XSD1.1.
验证 XML
但我的要求是解析断言值并转换为 Java脚本函数。
考虑以下断言示例:这里我需要解析双引号""之间的值,并根据条件到达一个Java脚本函数。
xsd:assert test="(exists(companyName) and companyTier='TierOne')"
有没有办法达到上面的要求?
任何帮助或建议都会对我有很大帮助。
................................................ ...................................
感谢您的回答。
通过关闭 sax validaiton 将允许我解析断言标记值。
但我的要求是将 XSD1.1 特性的那些断言值(如下所示)转换为 Java 正则表达式或任何可以评估的表达式
而且我应该有正确的链接,即这个断言标签属于哪个元素。
我了解到 xercesImpl-xsd11-2.12-beta 有 Xpath2.0 处理器可以使用。
但是我无法将 XSD 解析为存在断言标记的 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");
}
执行时控制台显示以下错误:
[错误] 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 已得到增强以包含跨字段验证。所以最终我不得不增强我的解析器来为每个元素捕获这些断言并到达 JavaScript 函数
对于 XSD 的每个元素。
所以我需要找到一种方法来解析存在于任何简单和复杂类型元素中的这些断言值。
您关于解析为原始类型的建议 XML 似乎不适合我现有的 XSOM 解析器。即我正在寻找解析器 API 来获取标签的值,因此该解决方案对任何 XSD.
都是通用的
关于此方法的任何建议都将有助于解决问题。
在关闭验证的情况下解析 XSD,以便您将其作为原始 XML 文件读取,那么它是 1.0 还是 1.1 都没有关系 XSD .
Set the http://xml.org/sax/features/validation
特征为假:
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature("http://xml.org/sax/features/validation", false);
} catch (ParserConfigurationException e) {
System.err.println("could not set parser feature");
}
我一直在使用 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 中的所有限制自动化到 Java 脚本函数,以便客户端 UI 可以被验证。
我进行了谷歌搜索,了解到 Xerces-j 只能针对 XSD1.1.
验证 XML但我的要求是解析断言值并转换为 Java脚本函数。
考虑以下断言示例:这里我需要解析双引号""之间的值,并根据条件到达一个Java脚本函数。
xsd:assert test="(exists(companyName) and companyTier='TierOne')"
有没有办法达到上面的要求? 任何帮助或建议都会对我有很大帮助。
................................................ ...................................
感谢您的回答。 通过关闭 sax validaiton 将允许我解析断言标记值。 但我的要求是将 XSD1.1 特性的那些断言值(如下所示)转换为 Java 正则表达式或任何可以评估的表达式 而且我应该有正确的链接,即这个断言标签属于哪个元素。
我了解到 xercesImpl-xsd11-2.12-beta 有 Xpath2.0 处理器可以使用。 但是我无法将 XSD 解析为存在断言标记的 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");
}
执行时控制台显示以下错误: [错误] 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 已得到增强以包含跨字段验证。所以最终我不得不增强我的解析器来为每个元素捕获这些断言并到达 JavaScript 函数 对于 XSD 的每个元素。 所以我需要找到一种方法来解析存在于任何简单和复杂类型元素中的这些断言值。
您关于解析为原始类型的建议 XML 似乎不适合我现有的 XSOM 解析器。即我正在寻找解析器 API 来获取标签的值,因此该解决方案对任何 XSD.
都是通用的关于此方法的任何建议都将有助于解决问题。
在关闭验证的情况下解析 XSD,以便您将其作为原始 XML 文件读取,那么它是 1.0 还是 1.1 都没有关系 XSD .
Set the http://xml.org/sax/features/validation
特征为假:
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature("http://xml.org/sax/features/validation", false);
} catch (ParserConfigurationException e) {
System.err.println("could not set parser feature");
}