Saxon-HE Java Extension Functions (Problem configuring) - java

I currently use Saxon9 open source version with extensions written in Java. I am trying to migrate to SaxonHE and I have read the documentation and examples shown here.
Java extension functions: full interface
and
Saxon Configuration File
When I try and execute my XSLT transformation I get errors like this when it encounters one of my external java functions.
XPST0017: Cannot find a 2-argument function named
Q{http://com.commander4j.Transformation.XSLT_Ext_NVL}nvl()
So here is what I've done so far.
My java extension function is written like this.
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.ExtensionFunctionCall;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.value.StringValue;
public class XSLT_Ext_NVL extends ExtensionFunctionDefinition
{
#Override
public SequenceType[] getArgumentTypes()
{
return new SequenceType[]{SequenceType.SINGLE_STRING, SequenceType.SINGLE_STRING};
}
#Override
public StructuredQName getFunctionQName()
{
return new StructuredQName("c4j_XSLT_Ext_NVL", "http://com.commander4j.Transformation.XSLT_Ext_NVL", "nvl");
}
#Override
public SequenceType getResultType(SequenceType[] arg0)
{
return SequenceType.SINGLE_STRING;
}
#Override
public ExtensionFunctionCall makeCallExpression()
{
return new ExtensionFunctionCall() {
#Override
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
String value = ((StringValue)arguments[0]).getStringValue();
String defaultValue = ((StringValue)arguments[1]).getStringValue();
String result = "";
if (value == null)
{
value = "";
}
result = value;
if (result.equals(""))
{
result = defaultValue;
}
return StringValue.makeStringValue(result);
}
};
}
}
I have created a Saxon configuration file which looks like this. My example looks a little different than the example on the Saxon website as that example includes the function name after the class name separated by a $ - when I tried it I got an error message that Saxon could not find the class.
edition="HE"
licenseFileLocation=""
label="c4jMiddleware">
<resources>
<extensionFunction>com.commander4j.Transformation.XSLT_Ext_NVL</extensionFunction>
</resources>
</configuration>
I am loading Configuration using this syntax.
Source xmlSource = new StreamSource(new File(System.getProperty("user.dir") + File.separator + "xml" + File.separator + "config" + File.separator +"SaxonConfiguration.xml"));
Configuration.readConfiguration(xmlSource);
Below is an extract from my XSLT which tries to invoke the java function.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:c4j="http://www.commander4j.com"
xmlns:c4j_XSLT_Ext_NVL="http://com.commander4j.Transformation.XSLT_Ext_NVL"
xmlns:c4j_XSLT_Ext="http://com.commander4j.Transformation.XSLTExtension"
exclude-result-prefixes="xs c4j c4j_XSLT_Ext" version="2.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
.
.
.
<xsl:template match="xml">
<xsl:param name="pack_conv" select="c4j_XSLT_Ext_NVL:nvl($pack_conv_temp, '1')"/>
If someone could give me a clue as to where I've gone wrong it would be most appreciated.
Dave

As Martin suggests, the most likely explanation is that you are not actually using the configuration you have created by reading the configuration file.

Related

Spring java.lang.NoClassDefFoundError error

I am new to spring framework and following the tutorial on tutorialspoint.com. After including every thing, while running the program it gives me following error:
Error: Unable to initialize main class com.raza.spring.MainApp
Caused by: java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
Below is my project structure:
enter image description here
Here is the code:
Class Hello:
package com.raza.spring;
public class Hello {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
}
Class MainApp:
package com.raza.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Hello obj = (Hello) context.getBean("helloWorld");
obj.getMessage();
}
}
Beans.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id = "helloWorld" class = "com.raza.spring.Hello">
<property name = "message" value = "Hello raza world !!!"/>
</bean>
</beans>
Not able to get what is wrong here. Thanks in advance.
I am trying tutorial on tutorialspoint.com and expecting an output on the console.
java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext tells that the Class you are using in your code is not accessible from your project.
In previous chapter on https://www.tutorialspoint.com/spring/spring_environment_setup.htm you probably downloaded spring library in step 4. Try adding it to your classpath: https://wiki.eclipse.org/FAQ_How_do_I_add_an_extra_library_to_my_project%27s_classpath%3F.
I highly recommend you start using maven. It allows you to add external libraries a lot easier, without having to manually download them from a git repo or a website.
Also, check the Baeldung courses. Their examples always use the latest Spring version https://www.baeldung.com/spring-tutorial

How to get Embeded/nested XML from a big XML file using SAX parser

We are performing some operations on embedded/Nested XML.I am using SAXParser to parse the entire XML file.I want to get the entire nested XML with tags and value.For example my XML looks like.
I want entire XML within the <ANY_ELEMENT>.....</ANY-ELEMENT> tag.
<?xml version="1.0" encoding="UTF-8"?>
<x:xMessage xmlns:x="http://www.connecture.com/integration/x" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.connecture.com/integration/x xMessageWrapper.xsd
">
<x:xMessageHeader>
<Version>850</Version>
<Source>Source</Source>
<Target>target</Target>
<Timestamp>2013-12-31T12:00:00</Timestamp>
<RequestID>123456</RequestID>
<ResponseID>54321</ResponseID>
<Priority>3</Priority>
<Username>Deepak</Username>
<Password>Kumar</Password>
</x:xMessageHeader>
<x:xMessageBody>
<ANY-ELEMENT>
<xEnveloped_834A1 xsi:schemaLocation="....." xmlns="......."
..........................
..........................
some Complex XML
..........................
..........................
..........................
</ANY-ELEMENT>
</x:XMessageBody>
</x:XMessage>
Handler class Sample code:
public class MessageWrapperHandler extends DefaultHandler {
private boolean bActualMessage = false;
private String actualMessage = null;
private long lengthActualMessage=0;
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equalsIgnoreCase("ANY-ELEMENT")) {
bActualMessage = true;
//lengthActualMessage=How to know the length of Child XML
}
}
public void characters(char ch[], int start, int length) {
if (bActualMessage) {
actualMessage = new String(ch, start, length);
//trying to get embedded XML
bActualMessage = false;
}
}
}
But since next element after is XML content so giving me nothing.SO How to achieve it.
EDIT: You are free to modify XML after <ANY-ELEMENT> like adding contents into CDATA
Instead of SAX, I would recommend using StAX (a StAX implementation is included in the JDK/JRE since Java SE 6). StAX is similar to SAX except instead of having the events pushed to you, you pull (request) them.
In the code below the XMLStreamReader is advanced to the ANY-ELEMENT element. Once it is at the correct position you can interact with it as you wish.
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xmlSource = new StreamSource("src/forum19559825/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xmlSource);
Demo demo = new Demo();
demo.positionXMLStreamReaderAtAnyElement(xsr);
demo.processAnyElement(xsr);
}
private void positionXMLStreamReaderAtAnyElement(XMLStreamReader xsr) throws Exception {
while(xsr.hasNext()) {
if(xsr.getEventType() == XMLStreamReader.START_ELEMENT && "ANY-ELEMENT".equals(xsr.getLocalName())) {
break;
}
xsr.next();
}
}
private void processAnyElement(XMLStreamReader xmlStreamReaderAtAnyElement) {
// TODO: Stuff
System.out.println("FOUND IT");
}
}

java and air integration ,the error is "3214 NativeProcessStartupInfo.executable does not specify a valid executable file. " on Windows machine

Below is my JavaProcess.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="windowedapplication1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.controls.Alert;
protected var process:NativeProcess;
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
var info:NativeProcessStartupInfo = new NativeProcessStartupInfo();// holds all info about native process
info.executable = new File("C:/Program Files/Java/jre1.6.0_22/bin"); // unix "/usr/bin/java"
//window program files/java
info.workingDirectory= File.applicationDirectory;
var args:Vector.<String> = new Vector.<String>();
args.push("-cp","../bin","net.riaspace.Main");
info.arguments = args;
process = new NativeProcess();
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,onDataOutput);
// this method will be fired when anything comes from java
process.start(info);
}
private function onDataOutput(event:ProgressEvent):void
{
var message:String = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
Alert.show(message);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button label="call java" click="process.standardInput.writeUTFBytes('hello\n')"/>
</s:WindowedApplication>
And My Main.Java is
package net.riaspace;
import java.util.Scanner;
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String input;
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext("Hello|stop"))
{
input = scanner.next();
if(input.equals("hello"))
{
System.out.println("Hello Flex");
}
else if(input.equals("stop"))
{
return;
}
}
}
}
NativeProcessStartupInfo.info The
File object that references an
executable on the host operating
system. This should be the full path
to the executable including any
extension required.
It looks like you are missing a reference to your .exe file.
I found an open source project " Flerry " to integrate Flex and Java Integration
Below is the link , it works for me.
http://www.riaspace.com/tag/java/

Validate an XML File Against Multiple Schema Definitions

I'm trying to validate an XML file against a number of different schemas (apologies for the contrived example):
a.xsd
b.xsd
c.xsd
c.xsd in particular imports b.xsd and b.xsd imports a.xsd, using:
<xs:include schemaLocation="b.xsd"/>
I'm trying to do this via Xerces in the following manner:
XMLSchemaFactory xmlSchemaFactory = new XMLSchemaFactory();
Schema schema = xmlSchemaFactory.newSchema(new StreamSource[] { new StreamSource(this.getClass().getResourceAsStream("a.xsd"), "a.xsd"),
new StreamSource(this.getClass().getResourceAsStream("b.xsd"), "b.xsd"),
new StreamSource(this.getClass().getResourceAsStream("c.xsd"), "c.xsd")});
Validator validator = schema.newValidator();
validator.validate(new StreamSource(new StringReader(xmlContent)));
but this is failing to import all three of the schemas correctly resulting in cannot resolve the name 'blah' to a(n) 'group' component.
I've validated this successfully using Python, but having real problems with Java 6.0 and Xerces 2.8.1. Can anybody suggest what's going wrong here, or an easier approach to validate my XML documents?
So just in case anybody else runs into the same issue here, I needed to load a parent schema (and implicit child schemas) from a unit test - as a resource - to validate an XML String. I used the Xerces XMLSchemFactory to do this along with the Java 6 validator.
In order to load the child schema's correctly via an include I had to write a custom resource resolver. Code can be found here:
https://code.google.com/p/xmlsanity/source/browse/src/com/arc90/xmlsanity/validation/ResourceResolver.java
To use the resolver specify it on the schema factory:
xmlSchemaFactory.setResourceResolver(new ResourceResolver());
and it will use it to resolve your resources via the classpath (in my case from src/main/resources). Any comments are welcome on this...
http://www.kdgregory.com/index.php?page=xml.parsing
section 'Multiple schemas for a single document'
My solution based on that document:
URL xsdUrlA = this.getClass().getResource("a.xsd");
URL xsdUrlB = this.getClass().getResource("b.xsd");
URL xsdUrlC = this.getClass().getResource("c.xsd");
SchemaFactory schemaFactory = schemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//---
String W3C_XSD_TOP_ELEMENT =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n"
+ "<xs:include schemaLocation=\"" +xsdUrlA.getPath() +"\"/>\n"
+ "<xs:include schemaLocation=\"" +xsdUrlB.getPath() +"\"/>\n"
+ "<xs:include schemaLocation=\"" +xsdUrlC.getPath() +"\"/>\n"
+"</xs:schema>";
Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(W3C_XSD_TOP_ELEMENT), "xsdTop"));
The schema stuff in Xerces is (a) very, very pedantic, and (b) gives utterly useless error messages when it doesn't like what it finds. It's a frustrating combination.
The schema stuff in python may be a lot more forgiving, and was letting small errors in the schema go past unreported.
Now if, as you say, c.xsd includes b.xsd, and b.xsd includes a.xsd, then there's no need to load all three into the schema factory. Not only is it unnecessary, it will likely confuse Xerces and result in errors, so this may be your problem. Just pass c.xsd to the factory, and let it resolve b.xsd and a.xsd itself, which it should do relative to c.xsd.
From the xerces documentation :
http://xerces.apache.org/xerces2-j/faq-xs.html
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
...
StreamSource[] schemaDocuments = /* created by your application */;
Source instanceDocument = /* created by your application */;
SchemaFactory sf = SchemaFactory.newInstance(
"http://www.w3.org/XML/XMLSchema/v1.1");
Schema s = sf.newSchema(schemaDocuments);
Validator v = s.newValidator();
v.validate(instanceDocument);
I faced the same problem and after investigating found this solution. It works for me.
Enum to setup the different XSDs:
public enum XsdFile {
// #formatter:off
A("a.xsd"),
B("b.xsd"),
C("c.xsd");
// #formatter:on
private final String value;
private XsdFile(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
Method to validate:
public static void validateXmlAgainstManyXsds() {
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
String xmlFile;
xmlFile = "example.xml";
// Use of Enum class in order to get the different XSDs
Source[] sources = new Source[XsdFile.class.getEnumConstants().length];
for (XsdFile xsdFile : XsdFile.class.getEnumConstants()) {
sources[xsdFile.ordinal()] = new StreamSource(xsdFile.getValue());
}
try {
final Schema schema = schemaFactory.newSchema(sources);
final Validator validator = schema.newValidator();
System.out.println("Validating " + xmlFile + " against XSDs " + Arrays.toString(sources));
validator.validate(new StreamSource(new File(xmlFile)));
} catch (Exception exception) {
System.out.println("ERROR: Unable to validate " + xmlFile + " against XSDs " + Arrays.toString(sources)
+ " - " + exception);
}
System.out.println("Validation process completed.");
}
I ended up using this:
import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.IOException;
.
.
.
try {
SAXParser parser = new SAXParser();
parser.setFeature("http://xml.org/sax/features/validation", true);
parser.setFeature("http://apache.org/xml/features/validation/schema", true);
parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "http://your_url_schema_location");
Validator handler = new Validator();
parser.setErrorHandler(handler);
parser.parse("file:///" + "/home/user/myfile.xml");
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException ex) {
e.printStackTrace();
}
class Validator extends DefaultHandler {
public boolean validationError = false;
public SAXParseException saxParseException = null;
public void error(SAXParseException exception)
throws SAXException {
validationError = true;
saxParseException = exception;
}
public void fatalError(SAXParseException exception)
throws SAXException {
validationError = true;
saxParseException = exception;
}
public void warning(SAXParseException exception)
throws SAXException {
}
}
Remember to change:
1) The parameter "http://your_url_schema_location" for you xsd file location.
2) The string "/home/user/myfile.xml" for the one pointing to your xml file.
I didn't have to set the variable: -Djavax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema=org.apache.xerces.jaxp.validation.XMLSchemaFactory
Just in case, anybody still come here to find the solution for validating xml or object against multiple XSDs, I am mentioning it here
//Using **URL** is the most important here. With URL, the relative paths are resolved for include, import inside the xsd file. Just get the parent level xsd here (not all included xsds).
URL xsdUrl = getClass().getClassLoader().getResource("my/parent/schema.xsd");
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdUrl);
JAXBContext jaxbContext = JAXBContext.newInstance(MyClass.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
/* If you need to validate object against xsd, uncomment this
ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<MyClass> wrappedObject = objectFactory.createMyClassObject(myClassObject);
marshaller.marshal(wrappedShipmentMessage, new DefaultHandler());
*/
unmarshaller.unmarshal(getClass().getClassLoader().getResource("your/xml/file.xml"));
If all XSDs belong to the same namespace then create a new XSD and import other XSDs into it. Then in java create schema with the new XSD.
Schema schema = xmlSchemaFactory.newSchema(
new StreamSource(this.getClass().getResourceAsStream("/path/to/all_in_one.xsd"));
all_in_one.xsd :
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ex="http://example.org/schema/"
targetNamespace="http://example.org/schema/"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:include schemaLocation="relative/path/to/a.xsd"></xs:include>
<xs:include schemaLocation="relative/path/to/b.xsd"></xs:include>
<xs:include schemaLocation="relative/path/to/c.xsd"></xs:include>
</xs:schema>

Why is Swing Parser's handleText not handling nested tags?

I need to transform some HTML text that has nested tags to decorate 'matches' with a css attribute to highlight it (like firefox search).
I can't just do a simple replace (think if user searched for "img" for example), so I'm trying to just do the replace within the body text (not on tag attributes).
I have a pretty straightforward HTML parser that I think should do this:
final Pattern pat = Pattern.compile(srch, Pattern.CASE_INSENSITIVE);
Matcher m = pat.matcher(output);
if (m.find()) {
final StringBuffer ret = new StringBuffer(output.length()+100);
lastPos=0;
try {
new ParserDelegator().parse(new StringReader(output.toString()),
new HTMLEditorKit.ParserCallback () {
public void handleText(char[] data, int pos) {
ret.append(output.subSequence(lastPos, pos));
Matcher m = pat.matcher(new String(data));
ret.append(m.replaceAll("<span class=\"search\">$0</span>"));
lastPos=pos+data.length;
}
}, false);
ret.append(output.subSequence(lastPos, output.length()));
return ret;
} catch (Exception e) {
return output;
}
}
return output;
My problem is, when I debug this, the handleText is getting called with text that includes tags! It's like it's only going one level deep. Anyone know why? Is there some simple thing I need to do to HTMLParser (haven't used it much) to enable 'proper' behavior of nested tags?
PS - I figured it out myself - see answer below. Short answer is, it works fine if you pass it HTML, not pre-escaped HTML. Doh! Hope this helps someone else.
<span>example with nested <p>more nesting</p>
</span> <!-- all this gets thrown together -->
Seems to work fine for me using JDK6 on XP. I wrapped your sample HTML with head and body tags. I got three lines of output:
a) example with
b) nested
c) more nesting
Here's the code I used:
import java.io.*;
import java.net.*;
import javax.swing.text.html.parser.*;
import javax.swing.text.html.*;
public class ParserCallbackText extends HTMLEditorKit.ParserCallback
{
public void handleText(char[] data, int pos)
{
System.out.println( data );
}
public static void main(String[] args)
throws Exception
{
Reader reader = getReader(args[0]);
ParserCallbackText parser = new ParserCallbackText();
new ParserDelegator().parse(reader, parser, true);
}
static Reader getReader(String uri)
throws IOException
{
// Retrieve from Internet.
if (uri.startsWith("http:"))
{
URLConnection conn = new URL(uri).openConnection();
return new InputStreamReader(conn.getInputStream());
}
// Retrieve from file.
else
{
return new FileReader(uri);
}
}
}
Sorry for the misleading question - I found my problem, and it wasn't included in my description - my input string had been pre-processed so I was looking at text such as
<span>example with <a href="#"> nested >/a< >p<more nesting>/p<
</span> <!-- well of course it all gets thrown together -->

Categories