Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new module metafacture-xslt for XSL Transformations #281

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions metafacture-runner/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ dependencies {
plugins project(':metafacture-strings')
plugins project(':metafacture-triples')
plugins project(':metafacture-xml')
plugins project(':metafacture-xslt')
plugins project(':metamorph')

// The plugins configuration needs to be on the runtime classpath:
Expand Down
27 changes: 27 additions & 0 deletions metafacture-xslt/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2018 Deutsche Nationalbibliothek
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

ext.mavenName = 'Metafacture XSLT'
description = 'Modules for XSL transformations on XML documents'

dependencies {
api project(':metafacture-framework')
implementation 'net.sf.saxon:Saxon-HE:9.8.0-10'
implementation 'org.slf4j:slf4j-api:1.7.21'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.5.5'
testImplementation project(':metafacture-xml')
}
43 changes: 43 additions & 0 deletions metafacture-xslt/src/main/java/org/metafacture/xslt/ApplyXslt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2018 Deutsche Nationalbibliothek
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.metafacture.xslt;

import net.sf.saxon.s9api.Destination;
import net.sf.saxon.s9api.SAXDestination;
import org.metafacture.framework.FluxCommand;
import org.metafacture.framework.XmlReceiver;
import org.metafacture.framework.annotations.Description;
import org.metafacture.framework.annotations.In;
import org.metafacture.framework.annotations.Out;
import org.metafacture.xslt.adapter.XmlContentHandler;

@In(XmlReceiver.class)
@Out(XmlReceiver.class)
@Description("Transforms generic XML (SAX event stream) by applying a XSLT using a custom stylesheet.")
@FluxCommand("apply-xslt")
public class ApplyXslt extends DefaultXsltPipe<XmlReceiver>
{
public ApplyXslt(String stylesheetId)
{
super(stylesheetId);
}

@Override
Destination getDestination()
{
return new SAXDestination(new XmlContentHandler(getReceiver()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2018 Deutsche Nationalbibliothek
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.metafacture.xslt;

import net.sf.saxon.s9api.*;
import org.metafacture.framework.MetafactureException;
import org.metafacture.framework.Receiver;
import org.metafacture.framework.helpers.DefaultXmlPipe;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import javax.xml.transform.stream.StreamSource;
import java.io.File;

public abstract class DefaultXsltPipe<R extends Receiver> extends DefaultXmlPipe<R>
{
private Processor processor;
private DocumentBuilder documentBuilder;
private BuildingContentHandler buildingContentHandler;
private XsltTransformer transformer;

public DefaultXsltPipe(String stylesheetId)
{
this.processor = new Processor(false);
this.documentBuilder = processor.newDocumentBuilder();
try
{
this.transformer = processor
.newXsltCompiler()
.compile(new StreamSource(new File(stylesheetId)))
.load();
}
catch (SaxonApiException e)
{
throw new MetafactureException(e);
}
}

public Processor getProcessor()
{
return processor;
}

abstract Destination getDestination();

@Override
public void onSetReceiver()
{
transformer.setDestination(getDestination());
}

@Override
public void startDocument()
{
try
{
buildingContentHandler = documentBuilder.newBuildingContentHandler();
buildingContentHandler.startDocument();
} catch (SaxonApiException|SAXException e)
{
throw new MetafactureException(e);
}
}

@Override
public void endDocument()
{
try
{
buildingContentHandler.endDocument();
processor.writeXdmValue(buildingContentHandler.getDocumentNode(), transformer);
}
catch (SAXException|SaxonApiException e)
{
throw new MetafactureException(e);
}
}

@Override
public void startElement(final String uri, final String localName,
final String qName, final Attributes attributes)
{
try
{
buildingContentHandler.startElement(uri, localName, qName, attributes);
}
catch (SAXException e)
{
throw new MetafactureException(e);
}
}

@Override
public void endElement(String uri, String localName, String qName)
{
try
{
buildingContentHandler.endElement(uri, localName, qName);
}
catch (SAXException e)
{
throw new MetafactureException(e);
}
}

@Override
public void characters(char[] ch, int start, int length)
{
try
{
buildingContentHandler.characters(ch, start, length);
}
catch (SAXException e)
{
throw new MetafactureException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright 2018 Deutsche Nationalbibliothek
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.metafacture.xslt;

import java.io.IOException;


import org.metafacture.framework.XmlReceiver;
import org.metafacture.framework.helpers.DefaultXmlPipe;
import org.xml.sax.*;

public class ForwardingSaxPipe extends DefaultXmlPipe<XmlReceiver>
{
@Override
public void setDocumentLocator(final Locator locator) {
getReceiver().setDocumentLocator(locator);
}

@Override
public void startDocument() throws SAXException
{
getReceiver().startDocument();
}

@Override
public void endDocument() throws SAXException {
getReceiver().endDocument();
}

@Override
public void startPrefixMapping(final String prefix, final String uri)
throws SAXException {
getReceiver().startPrefixMapping(prefix, uri);
}

@Override
public void endPrefixMapping(final String prefix) throws SAXException {
getReceiver().endPrefixMapping(prefix);
}

@Override
public void startElement(final String uri, final String localName, final String qName,
final Attributes atts) throws SAXException {
getReceiver().startElement(uri, localName, qName, atts);
}

@Override
public void endElement(final String uri, final String localName, final String qName)
throws SAXException {
getReceiver().endElement(uri, localName, qName);
}

@Override
public void characters(final char[] ch, final int start, final int length)
throws SAXException {
getReceiver().characters(ch, start, length);
}

@Override
public void ignorableWhitespace(final char[] ch, final int start, final int length)
throws SAXException {
getReceiver().ignorableWhitespace(ch, start, length);
}

@Override
public void processingInstruction(final String target, final String data)
throws SAXException {
getReceiver().processingInstruction(target, data);
}

@Override
public void skippedEntity(final String name) throws SAXException {
getReceiver().skippedEntity(name);
}

@Override
public void notationDecl(final String name, final String publicId, final String systemId)
throws SAXException {
getReceiver().notationDecl(name, publicId, systemId);
}

@Override
public void unparsedEntityDecl(final String name, final String publicId,
final String systemId, final String notationName) throws SAXException {
getReceiver().unparsedEntityDecl(name, publicId, systemId, notationName);
}

@Override
public InputSource resolveEntity(final String publicId, final String systemId)
throws SAXException, IOException
{
getReceiver().resolveEntity(publicId, systemId);
return null;
}

@Override
public void warning(final SAXParseException exception) throws SAXException {
getReceiver().warning(exception);
}

@Override
public void error(final SAXParseException exception) throws SAXException {
getReceiver().error(exception);
}

@Override
public void fatalError(final SAXParseException exception) throws SAXException {
getReceiver().fatalError(exception);
}

@Override
public void startDTD(final String name, final String publicId, final String systemId)
throws SAXException {
getReceiver().startDTD(name, publicId, systemId);
}

@Override
public void endDTD() throws SAXException {
getReceiver().endDTD();
}

@Override
public void startEntity(final String name) throws SAXException {
getReceiver().startEntity(name);
}

@Override
public void endEntity(final String name) throws SAXException {
getReceiver().endEntity(name);
}

@Override
public void startCDATA() throws SAXException {
getReceiver().startCDATA();
}

@Override
public void endCDATA() throws SAXException {
getReceiver().endCDATA();
}

@Override
public void comment(final char[] chars, final int start, final int length)
throws SAXException {
getReceiver().comment(chars, start, length);
}
}
Loading