經過幾天的混淆,並嘗試使用XSD驗證XML文檔的不同庫(我100%肯定是有效的根據XSD),我終於發現,原因是org.w3c.dom.DocumentBuilder
和org.w3c.dom.Document
決定將一堆屬性潛入DOM中。以下是我收到的許多驗證錯誤之一:爲什麼org.w3c.dom.DocumentBuilder偷偷向XML元素添加屬性
元素'API_Version'的屬性'high_value_range'的值'127'對於相應的屬性使用無效。屬性'high_value_range'具有固定值'4294967295'。
正如您在此示例test.xml
文件中看到,我不指定屬性'high_value_range'
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE My_Doc SYSTEM "MyDoc.dtd">
<My_Doc xmlns="http://my.namespace.org">
<Package>
<API_Version>1</API_Version>
</Package>
</My_Doc>
這裏是解析XML文件和打印DOM代碼:
package client;
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.*;
import org.w3c.dom.*;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class Writer
{
//method to convert Document to String
public static String getStringFromDocument(Document doc)
{
try
{
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
javax.xml.transform.Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
return writer.toString();
}
catch(TransformerException ex)
{
ex.printStackTrace();
return null;
}
}
public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException
{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc;
doc = dBuilder.parse(new File("data/test.xml"));
System.out.println(getStringFromDocument(doc));
}
}
最後,打印出解析的Document
並導致後續驗證失敗的結果:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<My_Doc xmlns="http://my.namespace.org" element_tag="GROUP" element_type="GROUP">
<Package>
<API_Version element_type="FIELD" field_type="INTEGER" value_upper_range="127">1</API_Version>
</Package>
</My_Doc>
這裏是MyDoc.dtd
重現:
<?xml version='1.0' encoding='UTF-8' ?>
<?My_Application DTD_Version='6.5'?>
<!ELEMENT My_Doc (Package)>
<!ATTLIST My_Doc element_tag CDATA #FIXED 'GROUP'
element_type CDATA #FIXED 'GROUP'
xmlns CDATA #FIXED 'http://my.namespace.org' >
<!ELEMENT Package (API_Version)>
<!ELEMENT API_Version (#PCDATA)>
<!ATTLIST API_Version element_type CDATA #FIXED 'FIELD'
field_type CDATA #FIXED 'INTEGER'
high_value_range CDATA #FIXED '127' >
<?DTD_End Dummy_Processing_Instruction='END'?>
爲什麼DocumentBuilder
將所有多餘的東西以及如何從這樣做,阻止它?
這聽起來不太可能。請提供[mcve],以便我們自己重現問題。 (出於興趣,如果刪除DTD,是否會改變任何內容?) –
@JonSkeet我無法共享數據,DTD或XSD。充其量我可以分享所有的代碼,如果你認爲這將有所幫助,但我提供的東西除了像'Class',try/catch','main','import'等垃圾。是的,如果我刪除在XML文件中引用DTD,那麼'DocumentBuilder'不會添加所有這些東西。 –
而且我同意這聽起來不太可能,我對你感到困惑,一定是一個很好的問題來破壞你;) –