На предыдущем проекте пришлось много сражаться с особенностями open source библиотек, которые мы использовали. Причём на форумах тоже было очень молчаливо, а задания делать надо было. Тогда я и заразился любовью в копании в исходниках open source библиотеки, чтобы решить свою проблему, очевидный и очень эффективный метод :)
Было найдено, что DocmentBuilderImpl использует объект интерфейса XMLParserConfiguration, для построения дерева объектов. Вызывая у него метод parse. И заменить его на свою реализацию не так уж сложно, просто определить системное свойство.
- System.setProperty("org.apache.xerces.xni.parser.XMLParserConfiguration", "a.MyConfig");
Теперь осталось только написать этот MyConfig. Писать с нуля лениво и несколько глупо. Поэтому в качестве базиса я выбрал класс NonValidatingConfiguration. Да и тут очередная абстракция :) он использует объект интерфейса XMLDocumentScanner для своего рода сканера-sax-парсера. Его мы только и заменим в этом классе конфига, путем переопределения метода configurePipeline.
- public class MyConfig extends NonValidatingConfiguration {
- private MyScanner myScanner;
- @Override
- @SuppressWarnings("unchecked")
- protected void configurePipeline() {
- if (myScanner == null) {
- myScanner = new MyScanner();
- addComponent((XMLComponent) myScanner);
- }
- super.fProperties.put(DOCUMENT_SCANNER, myScanner);
- super.fScanner = myScanner;
- super.fScanner.setDocumentHandler(this.fDocumentHandler);
- super.fLastComponent = fScanner;
- }
- }
- private static class MyScanner extends XMLDocumentScannerImpl {
- @Override
- protected void scanEntityReference() throws IOException, XNIException {
- // name
- String name = super.fEntityScanner.scanName();
- if (name == null) {
- reportFatalError("NameRequiredInReference", null);
- return;
- }
- super.fDocumentHandler.characters(new XMLString(("&" + name + ";")
- .toCharArray(), 0, name.length() + 2), null);
- // end
- if (!super.fEntityScanner.skipChar(';')) {
- reportFatalError("SemicolonRequiredInReference",
- new Object[] { name });
- }
- fMarkupDepth--;
- }
- }
Ну и в качестве небольшого бонуса расскажу продолжение истории. Есть у нас DOM дерево объектов и мы его решим сохранить в xml файл, как у нас это делается через класс Transformer.
- Document doc = ....
- TransformerFactory tFactory = TransformerFactory.newInstance();
- Transformer transformer = tFactory.newTransformer();
- StringWriter sw = new StringWriter();
- transformer.transform(new DOMSource(doc), new StreamResult(sw));
- <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:output method="xml">
- <xsl:template match="@*|node()">
- <xsl:choose>
- <xsl:when test="self::text()">
- <xsl:value-of disable-output-escaping="yes" select=".">
- </xsl:value-of></xsl:when>
- <xsl:otherwise>
- <xsl:copy>
- <xsl:apply-templates select="@*|node()"></xsl:apply-templates>
- </xsl:copy>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
- </xsl:output></xsl:stylesheet>
Комментариев нет:
Отправить комментарий