我有一個類似XML的文件:解析XML並獲得無約束力的命名空間DOM樹 - Java的
<p>something</p>
<ac:image>
<ri:attachment ri:filename="IMAGE.PNG" />
</ac:image>
<ac:macro ac:name="screenshot">
<ac:default-parameter>IMAGE.ss</ac:default-parameter>
</ac:macro>
<p>something</p>
我需要XSLT模板來改造它 - 我想所有<ac:image>
與<ac:macro ac:name="screenshot">
取代。一般來說,解析和轉換格式良好的XML並非常容易。我的情況相當不同。
如您所見,它沒有根元素和XML序言。但它不是一個問題,我可以添加<?xml version="1.0"?>
,敷用,如<root>
任意元素的內容,以避免異常:
Caused by: org.jdom.input.JDOMParseException: Error on line 1: Content is not allowed in prolog.
示例XML包含三個命名空間 - 默認情況下,ac
和ri
。由於代碼將在客戶指定的內容上運行,因此可能會有其他一些我不知道的名稱空間。我不能夠解析XML之前,所有的命名空間綁定,所以我遇到異常:
Caused by: org.xml.sax.SAXParseException: Content is not allowed in prolog.
我發現某處在互聯網上,SAX解析器能夠解析個XML的模式,它不能解決上命名空間。在默認模式下,您獲得namespace=ac
和element=macro
,而在非名稱空間模式下,您不會獲得名稱空間並且不會獲得element=ac:macro
。這是理想的。您只需要在解析器上設置SAX功能:namespaces=false
,namespace-prefixes=true
。
final XMLReader sax = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
sax.setFeature("http://xml.org/sax/features/validation", false);
sax.setFeature("http://xml.org/sax/features/namespaces", false);
sax.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
sax.parse(new InputSource(new StringReader(content))); // parse returns void
它不會拋出任何異常,所以它看起來像XML解析沒有錯誤。但是,我需要一個DOM樹,以便我可以使用XSLT進行轉換。讓我們用JDOM則:
// all classes are org.jdom.*
final SAXBuilder sax = new SAXBuilder(false); // validate=false
sax.setFeature("http://xml.org/sax/features/namespaces", false);
sax.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
final Document document = sax.build(new StringInputStream(content));
不幸的是,我得到一個異常:
Caused by: org.jdom.IllegalNameException: The name "" is not legal for JDOM/XML elements: XML names cannot be null or empty.
at org.jdom.Element.setName(Element.java:206)
at org.jdom.Element.<init>(Element.java:140)
at org.jdom.Element.<init>(Element.java:152)
at org.jdom.DefaultJDOMFactory.element(DefaultJDOMFactory.java:138)
at org.jdom.input.SAXHandler.startElement(SAXHandler.java:511)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.dtd.XMLDTDValidator.startElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl$ContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:453)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:770)
at com.screensnipe.confluence.macro.XhtmlImageMacroReplacer.replaceImageMacroInText(XhtmlImageMacroReplacer.java:118)
JDOM抱怨一個非法的標記名稱<>
。當然,我沒有這樣的。看起來JDOM在SAXHandler.java中有錯誤:511,應該是element = factory.element(qName);
。
我也試過XOM。 XOM does not work with "namespaces" feature set to false。
我也試過TagSoup庫。我不喜歡它,因爲它搞亂了輸出XML。添加XML prolog和根元素不是問題。混淆命名空間是。
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<p>something</p>
<ac:image xmlns:ac="urn:x-prefix:ac"> <!-- :(-->
<ri:attachment xmlns:ri="urn:x-prefix:ri" ri:filename="IMAGE.PNG" />
</ac:image>
...
問題是:如何從我的XML中獲取DOM樹? (Java)不寫我的JDOM版本。我將不勝感激工作解決方案。只需解析並獲取DOM樹。與TagSoup庫一樣,名稱空間沒有被破壞的樹。
或更多以目標爲中心的問題:如何用<ac:macro ac:name="screenshot">
替換<ac:image>
而不觸及其他標籤? (Java)所有其他標記,名稱空間或其他應該不受影響。 (不建議任何正則表達式)
嗯...不完美的方式,但它很容易,會做的東西。謝謝,upvoted。如果沒有更好的答案,我會接受你的答案。 :) – Nowaker