What I am trying to achieve is (using Saxon-B 9.1):
1) Run XSLT transformation with object of below Example class as parameter
2) Object's properties are populated using reflexive extension function with selected Nodes
3) Run second XSLT transformation (on different XML input) and pass the above object with populated values as parameter
4) Insert XML nodes from the object into output document
My class is below:
public class Example {
. private NodeSet test;
. public RequestInfo() {}
. public void settest(NodeList t) {
. this.test = t;
. }
. public NodeList gettest() {
. return test;
. }
}
First transformation seems to populate my object fine (using settest() method within XSLT) - I can see correct nodes added to the NodeList.
However, I am getting below error when running 2nd transformation and calling gettest() method from within XSLT:
NodeInfo returned by extension function was created with an incompatible Configuration
I was thinking should I not use NodeList but maybe some different, equivalent type that would be recognised by Saxon? I tried it with NodeSet but got same error message.
Any help on this would be appreciated.
You haven't shown enough information to see exactly what you are doing wrong, but I can try and explain the error message. Saxon achieves its fast performance in part by allocating integer codes to all the names used in your XML documents and stylesheets, and using integer comparisons to compare names. The place where the mapping of integers to names is held is the NamePool, and the NamePool is owned by the Saxon Configuration object; so all documents, stylesheets, etc participating in a transformation must be created under the same Configuration (it's a bit like the DOM rule that all Nodes must be created under the Document they are attached to). The message means that you've got at least two different Configuration objects around. A Configuration gets created either explicitly by your application, or implicitly when you create a TransformerFactory, an XPathFactory, or other such objects.
I wonder whether this mixing of XSLT and Java code is really a good idea? Often when I see it, the Java code is being used because people haven't mastered how to achieve the desired effect in XSLT. There are many good reasons for NOT using the DOM with Saxon: it's very slow, it requires more lines of code, it's not thread-safe, it's harder to debug, ...
Related
I wanted to do some processing on values in yml file. Someone suggested me to use snakeYAML's low-level API for this purpose. So I've written some code using that but I'm pretty much stuck due to the following reasons.
Here's the code I've wrote:
public static void main(String[] args) throws Exception{
Yaml yaml = new Yaml();
FileReader contentFromFile=new FileReader("/Users/prakash.tiwari/Desktop/yamlInput.yml");
for (Node node : yaml.composeAll(contentFromFile)) {
System.out.println(node);
}
}
Here is my yamlInput.yml:
Prakash:
Lucky:
Number: 11
Really? : NotAtAll
Here's what was printed on console(It was in a single line, I formatted it and added a comment to make it readable):
<org.yaml.snakeyaml.nodes.MappingNode
(
tag=tag:yaml.org,2002:map,
values=
{
key=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Prakash)>;
value=355629945 // Why is this a garbage value?
}
{
key=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Really?)>;
value=
<NodeTuple
keyNode=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Really?)>;
valueNode=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=NotAtAll)>
>
}
)>
At this point I can extract the valueNode which are also ScalarNode by searching for valueNode=<org.yaml.snakeyaml.nodes.ScalarNode and then process the value in this node .
But the issue is that I don't know why it puts a garbage value while composing map nodes. So here are my questions:
How to correctly compose yaml files so that map nodes appear correctly and not garbage values?
After I'm done processing and have successfully replaced the values with the processed ones, how do I put these back to a yaml file?
If you think this is a rubbish method to start with, please suggest me a better one.
The reason you get the „garbage value“ is because of this section in MappingValue's toString method:
if (node.getValueNode() instanceof CollectionNode) {
// to avoid overflow in case of recursive structures
buf.append(System.identityHashCode(node.getValueNode()));
} else {
buf.append(node.toString());
}
Since the composed graph may contain cycles (because anchors & aliases have been resolved at this stage of parsing), toString will not recurse into Collection nodes (i.e. Mappings and Sequences).
This means that your node tree has indeed be composed correctly and you simply should not use toString to inspect it. That answers your first question.
To write that back to a YAML file, use something like
Emitter emitter = new Emitter(/* e.g. a FileWriter */ writer, new DumperOptions());
for (Event event : yaml.serialize(/* the root node */ node)) {
emitter.emit(event);
}
To answer question 3: In the previous question, you mentioned that you want to change (encrypt) certain values and leave the others untouched. If that is the case, I suggest you use yaml.parse instead of yaml.compose because you lose fewer information when working on the event stream than when working on the composed graph (meaning that the output will be more similar to the input).
You can then go through the generated events, identify the events you want to alter and replace them with the altered events, and then use an Emitter like I showed in the code above.
I showed with some Python code here how to identify events in an event stream from a list of strings (kind-a „YAML-path“), however that code inserts events at the given path instead of altering them. The Python and Java API are somewhat similar, so if you can read Python, that code may help you.
Is there a way to record specific line/character positions from generated FreeMarker templates? The purpose would be to highlight specific sections of the generated output file without having to parse the generated output file.
For example, let's say I have this template:
function foo()
{
ordinary_crap();
ordinary_crap();
do_something_special();<#mark foospecial>
ordinary_crap();
}
function bar()
{
ordinary_crap();
do_something_really_special();<#mark barspecial>
ordinary_crap();
ordinary_crap();
}
function baz()
{
foo();<#mark foo_call_1>
ordinary_crap();
bar();<#mark bar_call_1>
}
I want the <#mark> directive not to yield any generated output, but to associate mark names foospecial, barspecial, foo_call_1 and bar_call_1 with the line and position-within-a-line of where the <#mark> directives are located in the generated output. The example above I showed independent single points but it would be also useful to have begin/end pairs to mark specific ranges.
The alternatives I can see are
parsing the output independently -- not always possible, for example what if there are several identical instances of something in the output, and I want to highlight a specific one of those?
adding "mark hints" and removing them via my own postprocessing step. For example
<mark name="years">Fourscore and seven</mark> years ago
something really brilliant happened to a really nice guy named
<mark name="niceguyname">Fred</mark>.
Then I could postprocess this and remove the <mark > tags (assuming they don't conflict with the rest of the content), recording positions as I go.
But both of these seem kind of hacky.
From your TemplateDirectiveModel implementation (I assume that's how you implement mark, not with #macro), call env.getCurrentDirectiveCallPlace(). The returned DirectiveCallPlace has getBeginColumn() and getBeginLine() methods.
I was writing a Java program, and when I tried to use a string, a suggestion that popped up was com.sun.org.apache.xpath.internal.operations.String.
What is com.sun.org.apache.xpath.internal.operations.String, and when should I use it?
I have looked online, but I cannot find the documentation.
Thank you!
You can work backwards based on the package name. The first piece that gives us a clue to what it does is Xpath. Then there's Apache, which is a the Apache Software Foundation. So it's an API called Xpath from Apache.
XPath is a language for parsing and processing XML content. It has some simple capabilities such as math or data conversions. In this case, String is a unary operator that converts text to a String, as opposed to a Number or a boolean. It has one static method operate:
public XObject operate(XObject right)
throws TransformerException
It takes an XObject of some unknown type and converts it to a String type.
An example snippet of XPath for String conversion would be, at its barest:
string($x) //convert variable x to a String
You probably would never need to call this, seeing as it is part of an internal package. It is most probably used when interpreting XML to get the result as a String for use with other Xpath internal components. Indeed, the returned result is an XObject with a type associated to it, so interpreting it as a normal Java String would break something. It is nice to helpful to know that it's there, and it is public per design, but you'd ever use this in the real world unless you're expanding on the xpath API yourself.
Source Package Tree
This is a class used by some Apache implementation that unfortunately shows up in your Java CodeAssist.
If you are using Eclipse you can check that out:
http://www.eclipse.org/forums/index.php/t/80401/
I'm trying to pass an XML document to an XSLT stylesheet as a parameter. I believe the code is using the oracle XDK for transformations (it's using JDK 1.4.2, and Spring, and I'm new to the codebase, so I'm not sure what is getting loaded in the end). In my first attempt, I just created a document object and set this as the parameter on the transformer, but attempts to copy the variable into the tree give no result. Questions that come to mind are:
is this even possible in the general case of XSLT transformers? (it seems like it should be, as generally XSLT variables/parameters can contain nodesets)
is it possible specifically with the oracle XDK (or xalan, which is also in the classpath)?
If so, how do I make it work?
The answer is that this is possible, however, it is non-intuitive, at least for the Oracle XSL processor. I tried the following (non-working) invocations (names changed to protect the innocent):
Document x = createDocumentForMe();
transformer.addParameter("param",x);
and
Document x = createDocumentForMe();
transformer.addParameter("param",new DOMSource(x));
(this second on the basis that maybe DOMSource would work because it was the java.xml.transform interface to the DOM). The invocation that worked for me in the end was to take the insight that XSL uses XPath, and the valid types for the variable are essentially strings or nodesets, and XPath returns nodesets. The following works for me:
Document x = createDocumentForMe();
XPathExpression xpe = XPathFactory.newInstance().newXPath().compile("/");
transformer.addParameter("param",xpe.evaluate(x, XPathConstants.NODESET));
Which basically uses XPath to get a nodeset containing only the root document of the passed in DOM object. However, this seems like a bit of a hack, and may not work with other XSL processors, so YMMV...
Are there any tools available for transforming types defined in an xsd schema (may or may not include other xsd files) into ActionScript value objects? I've been googling this for a while but can't seem to find any tools and I'm pondering wether writing such a tool would save us more time right now than to simply code our value objects by hand.
Another possibility I've been considering is using a tool such as XMLBeans to transform the types defined by the schema to Java classes and then converting those classes in ActionScript. However, I've come to realize that there are about a gazillion java -> as3 converters out there and the general consesus seems to be that they sort of work, ie, I have no idea which tool is a good fit.
Any thoughts?
For Java -> AS generation, check out GAS3 from the Granite Data Services project:
http://www.graniteds.org/confluence/display/DOC/2.+Gas3+Code+Generator
This is the kind of thing you can write yourself too, especially if you leverage a tool like Ant and write a custom Task to handle it. In fact, I worked on this last year and open-sourced it:
https://github.com/cliffmeyers/Java2As
I don't have any kind of translator either. What I do is have an XML object wrapped by an ActionScript object. Then you have a getter/setter for each value that converts xml->whatever and whatever->XML. You still have to write the getter/setter though, but you can have a macro/snippit handle that work for you.
So for XML like:
<person>
<name>Bob</name>
...
</person>
Then we have an XML Object Wrapper class and extend it. Normally
class XMLObjectWrapper
{
var _XMLObject:XML;
function set XMLObject(xml:XML):void
{
_XMLObject = xml;
}
function get XMLObject():XML
{
return _XMLObject;
}
}
class person extends XMLObjectWrapper
{
function set name(value:String):void
{
_XMLObject.name = value;
}
function get name():String
{
return _XMLObject.name;
}
}