我继续寻找可以帮助我的东西,但没有成功,所以我转向你。
我正在编写一个Java代码,需要根据给定的动态模式验证XML。我给了2个XSD,其中一个引用了另一个的元素。 要求是仅使用根XSD中的元素的XML将是有效的。一个例子可以解决问题。
XSD示例
第一个:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://root/beer"
xmlns="http://root/beer" xmlns:chl="http://child/earth"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://child/earth" schemaLocation="testing_child.xsd"/>
<xs:element name="head">
<xs:complexType>
<xs:sequence>
<xs:element ref="chl:banana"/>
</xs:sequence>
</xs:complexType>
</xs:element>
第二个:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://child/earth"
xmlns="http://child/earth" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="banana">
<xs:complexType>
<xs:sequence>
<xs:element name="leaf" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
现在,我希望以下XML有效:
<head xmlns="http://root/beer">
<banana xmlns="http://child/earth">
<leaf>yo</leaf>
</banana>
</head>
但是(这是棘手的一点),这个不会:
<banana xmlns="http://child/earth">
<leaf>yo</leaf>
</banana>
我尝试使用带有SAX和DOM的Validator,使用LSResourceResolver和没有,但得到了相同的结果 - 两个XML都是有效的,而不仅仅是父(/ root).... 我无法使用JAXB,因为我无法在XSD中构建类(它们保存在fs中的文件中)。 不,我也无法改变XSD。
如果您知道某种方式/过去做过类似事情并且可以帮助我,我会非常感激。
由于
答案 0 :(得分:0)
由于这显然符合XML Schema,因此没有合规验证者应该抱怨banana
作为顶级元素。
所以你需要一些额外的东西。
我最初考虑通过资源解析器中的临时处理使banana
成为一个抽象元素。但是banana
作为非根元素可能有效用法(例如,通过xs:element/@ref
)。
所以我建议做一些额外的验证 - 或者通过像Schematron这样的东西或只是#34;用Java编写自己的#34;
你可能在Java中使用Xerces。
Schema
对象,找出顶级元素及其位置。我就是这样做的。这将使您与验证器实现联系起来,但无论如何您的自定义都是专有的。
答案 1 :(得分:0)
正如@lexicore建议的那样,我添加了额外的验证代码(不是我写的最漂亮的东西,但它现在有用)。
如果有人提出异议:
public static void validate(String fileLocXSD, String fileLocXML) {
try {
boolean valid = false;
// Read data to strings
String xsd = dataFromFile(fileLocXSD);
xsd = xsd.toLowerCase();
String xml = dataFromFile(fileLocXML);
xml = xml.toLowerCase();
// Notice that parsing errors may occure
Document doc = getDocument(xsd);
Document docXML = getDocument(xml);
// Let's strip down the xsd and get what we want
ArrayList<String> listHeaders = new ArrayList<String>();
Element docElement = doc.getDocumentElement();
NodeList listElements = docElement.getChildNodes();
String ns = docElement.getAttribute("targetnamespace");
ns = ns==null?"":ns;
// Check all child elements of the doc element
for (int i=0; i<listElements.getLength(); i++) {
Node node = listElements.item(i);
if (node.getNodeName().contains("element")) {
listHeaders.add(((Element)node).getAttribute("name"));
}
}
// What about the xml ha? don't forget about it (or about Dre)
Element docXMLElement = docXML.getDocumentElement();
String nsXML = "";
String rootName = docXMLElement.getNodeName();
// Default ns in xml
if (!rootName.contains(":")) {
nsXML = docXMLElement.getAttribute("xmlns");
nsXML = nsXML==null?"":nsXML;
// No namespace
if (("").equals(ns) && ("").equals(nsXML)) {
for (int j=0; (j<listHeaders.size()) && (!valid); j++) {
if (listHeaders.get(j).equals(rootName)) {
valid = true;
}
}
} else if ((ns).equals(nsXML)) {
for (int j=0; (j<listHeaders.size()) && (!valid); j++) {
if (listHeaders.get(j).equals(rootName)) {
valid = true;
}
}
}
} else {
String shortNS = rootName.substring(0,rootName.indexOf(":"));
nsXML = docXMLElement.getAttribute("xmlns:"+shortNS);
rootName = rootName.substring(rootName.indexOf(":")+1);
// has to be namespace in xsd
if ((ns).equals(nsXML)) {
for (int j=0; (j<listHeaders.size()) && (!valid); j++) {
if (listHeaders.get(j).equals(rootName)) {
valid = true;
}
}
}
}
System.out.println(valid?"valid":"nope");
} catch (SAXParseException e) {
System.out.println("Parsing error: "+e.getMessage());
}catch (Exception e) {
System.out.println("holy shit: "+e.getMessage());
}
}
public static String dataFromFile(String fileLoc) {
String xml = "";
try {
BufferedReader b = new BufferedReader(new InputStreamReader(new FileInputStream(fileLoc),"UTF-8"));
StringBuilder builder = new StringBuilder();
String line = null;
while((line = b.readLine()) != null) {
builder.append(line);
}
xml = builder.toString();
xml = xml.trim().replaceFirst("^([\\W]+)<","<");
} catch (Exception e) {
System.err.println("Error reading file");
}
return xml;
}
public static Document getDocument(String xml) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xml)));
return doc;
}