I have an xslt 1.0 stylesheet which needs to be converted to xslt 2.0.
I found this question here: Convert XSLT 1.0 to 2.0 which deals with the same issue.
According to that changing version attribute to 2.0 would do the trick. But is that the only thing which needs to be done?
Thanks in advance
I think the choice of strategy for conversion depends on how good a set of regression tests you have.
If you have a good set of regression tests, or if the consequences of introducing an error are not severe, then I would recommend the following steps:
(a) change the version attribute to 2.0
(b) run your test cases using an XSLT 2.0 processor and see if they work
(c) examine any test discrepancies and identify their cause (perhaps 80% of the time it will work correctly first time with no discrepancies).
If you don't have good tests or if you can't afford to take any risks, then you might need a more cautious strategy. (The ultimate in caution, of course, is the "don't change anything" strategy - stick with 1.0). Perhaps the best advice in this case is to start the conversion project by writing more test cases. At the very least, collect together a sample of the source documents you are currently processing, and the output that is generated for these source documents, and then use a file comparison tool to compare the output you get after conversion.
There are a few incompatibilities between 1.0 and 2.0; the one you are most likely to encounter is that xsl:value-of (and many other constructs) in 1.0 ignore all nodes in the supplied input sequence after the first, whereas XSLT 2.0 outputs all the nodes in the supplied sequence. There are two ways of dealing with this problem. Either (my recommendation) identify the places where this problem occurs, and fix them, usually by changing select="X" to select="X[1]"; or change the version attribute on the xsl:stylesheet back to version="1.0", which causes the XSLT 2.0 processor to run in backwards compatibility mode. The disadvantage of relying on backwards compatibility mode is that you lose the benefits of the stronger type-checking in XSLT 2.0, which makes complex stylesheet code much easier to debug.
In my experience the problems you encounter in conversion are more likely to depend on processor/implementation changes than on W3C language changes. Your code might be using vendor-defined extension functions that aren't supported in the 2.0 processor, or it might be relying on implementation-defined behaviour such as collating sequences that varies from one processor to another. I have seen code, for example, that relied on the specific format of the output produced by generate-id(), which is completely implementation-dependent.
"XSL Transformations (XSLT) Version 2.0", §J, "Changes from XSLT 1.0 (Non-Normative)" lists most the differences between XSLT 1.0 and XSLT 2.0 that you need to be aware of.
Related
I'm maintaining a legacy tool of the company I work for written in C# and I'm converting it to .Net standard 2.0. It uses the Saxon-HE processor to process some XPaths and replace some configurations in files.
Its NuGet package on .NET has dependencies that do not allow the execution on all the .Net standard 2.0 compliant platforms (in my case both .Net Framework and .Net core), so I need to replace it with one another tool, better if the standard .Net XPath library.
The problem is that the tool uses some XPaths that perform complex operations such as concatenate strings and select an array item, and I don't know if it's a Saxon-specific syntax or regards a standard.
It is important to know this because if the XPaths are compliant to some XPath standard I could find one another way to process the same XPaths.
Here is some examples:
First:
for $row in /Item/SubItem[*]/SubSubItem return(concat($row, \"/ConcatValue\"))
Second:
/Item/SubItem[*]/SubSubItem/(add[#key=\"TheKey\"]/#value/string(), '')[1]
Do you know something about this XPath syntax?
Thank you
The XPath expressions you have given as examples require an XPath 2.0 processor but they are not specific to Saxon.
The expression
for $row in /Item/SubItem[*]/SubSubItem return(concat($row, \"/ConcatValue\"))
is a ForExpression, which is specific to XPath 2.0, and is not easily converted to XPath 1.0 because its result is a sequence of strings, and there is no such data type in XPath 1.0.
The expression
/Item/SubItem[*]/SubSubItem/(add[#key=\"TheKey\"]/#value/string(), '')[1]
is specific to XPath 2.0 because it uses a parenthesized expression on the RHS of the "/" operator; and again, because it returns a sequence of strings.
I'm afraid I can't advise you whether there exist XPath 2.0 libraries that run on .NET Core, which I assume is your requirement. Saxon cannot be made to run on .NET Core because of its dependency on IKVM, which doesn't support that platform and which (I gather) cannot readily be adapted to do so.
Note that XPath 2.0 is a subset of XQuery 1.0, so you could extend your search to XQuery 1.0 processors as well as XPath 2.0 processors.
Thanks to this comment I was able to test XPath2.Net and now everything works. I needed to change only one type of XPath definition
This one:
/Item/SubItem[*]/SubSubItem/(add[#key=\"TheKey\"]/#value/string(), '')[1]
Changes to
/Item/SubItem[*]/SubSubItem/(add[#key=\"TheKey\"]/#value/string(.), '')[1]
Please note the additional dot argument of the string() function.
This is strange as it should not be require the dot; in fact, per standard
In the zero-argument version of the function, $arg defaults to the
context item. That is, calling fn:string() is equivalent to calling
fn:string(.)
but XPath2 complains with this error
{"The function 'string'/0 was not found in namespace 'http://www.w3.org/2003/11/xpath-functions'"}
UPDATE:
After updating the XPath2.Net library to version 1.0.8 the string() syntax works.
I have a Groovy switch called (very) frequently in my application. VisualVM sampling shows that I spend around 20% of my application time in ScriptBytecodeAdapter.isCase().
Since all the cases are strings, my usage would be supported by the standard Java 7 string switch which should be more efficient.
Is it possible to ask Groovy to fallback to the standard Java switch ?
Remarks:
I can use ASTs (the switch it self is generated by an AST in SEMANTIC_ANALYSIS).
Other implementation options could be to use ifs/elses instead (I usually have < 20 cases) or a Map of Closures
Applying the Groovy CompileStatic transformation in your AST, after building your nodes, should cause your generated code to be statically compiled. Be sure that you are doing this programmatically in your code, not by adding the annotation to your transformation class.
In most cases the plain old Java version of code constructs will be more performant than the added Groovy syntax; however, it can be difficult to access the underlying Java constructs in some cases.
This should at least take it one step farther.
What is currently the best way to write SonarQube 4.5 checks for :
Bytecode Analysis
Source Analysis
Unfortunately, I could not find an up-to-date web page providing a clear explanation, and I see that existing checks use many deprecated classes and methods, use "bridges" about to be abandonned, checks are regularly removed from the codebase (such as the XPath rule).
I would like to be sure that the checks I'm about to write will be well written and durable.
So...
should I use BytecodeVisitor to analyse bytecode ?
should I use BaseTreeVisitor to analyse sourcecode ?
What is the replacement for org.sonar.api.rules.RuleRepository ?
What is the replacement for org.sonar.api.resources.Java ?
What is the replacement for org.sonar.api.rules.AnnotationRuleParser ?
How can I write XPath like rules (BaseTreeVisitor is using SSLR and if I'm not wrong SonarQube is moving away from SSLR / AbstractXPathCheck is part of sslr squid bridge.)
What else should I know ?
In other words I'm a bit lost.
Thank you in advance for your help.
First thanks for your feedback,
There are in fact many questions in your question (sic) :
The way to write custom checks for Java as of today is to use the BaseTreeVisitor. All the other ways are now deprecated and we are working to be able to remove them (but it is not always straightforward as some of them requires a complete semantic analysis to be removed). What is currently lacking from this api is the access to the semantic analysis to be able to request type information read from bytecode.
You can have a look at this project : https://github.com/SonarSource/sonar-examples/tree/master/plugins/java-custom-rules
For all the other questions, please ask them on the mailing list.
(Small notes though : BaseTreeVisitor does not use SSLR directly, the java plugin is not moving away from SSLR rather from one class, specifically ASTNode, in order to work on a SyntaxTree with a class specific for each type of node, The drop of Xpath checks occurs in that logic of moving away from a non-typed SyntaxTree).
So iOS 6 deprecates presentModalViewController:animated: and dismissModalViewControllerAnimated:, and it replaces them with presentViewController:animated:completion: and dismissViewControllerAnimated:completion:, respectively. I suppose I could use find-replace to update my app, although it would be awkward with the present* methods, since the controller to be presented is different every time. I know I could handle that situation with a regex, but I don't feel comfortable enough with regex to try using it with my 1000+-files-big app.
So I'm wondering: Does Xcode have some magic "update deprecated methods" command or something? I mean, I've described my particular situation above, but in general, deprecations come around with every OS release. Is there a better way to update an app than simply to use find-replace?
You might be interested in Program Transformation Systems.
These are tools that can automatically modify source code, using pattern-directed source-to-source transformations ("if you see this source-level pattern, replace it by that source-level pattern") that operate on code structures rather than text. Done properly, these transformations can be reliable and semantically correct, and they're a lot easier to write than low-level procedural code that navigates and smashes nanoscopic actual tree structures.
It is not the case that using such tools is easy; such tools have to know how to parse the language of interest into compiler data structures, (e.g., ObjectiveC), process the patterns, and regenerate compilable source code from the modified structures. Even with the basic transformation engine, somebody needs to carefully define parsers (and unparsers!) for the dialects of the languages of interest. And it takes time to learn how to use such a even if you have such parsers/unparsers. This is worth it if the changes you need to make are "regular" (in the program transformation sense, not the regexp sense) and widespread (as yours seem to be).
Our DMS Software Reengineering toolkit has an ObjectiveC front end, and can carry out such transformations.
no there is no magic like that
I am aware that by default Java does not have the so-called eval (what I pronounce as "evil") method. This sounds like a bad thing—knowing you do not have something which so many others do. But even worse seems being notified that you can't have it.
My question is: What is solid reasoning behind it? I mean, Google'ing this just returns a massive amount of old data and bogus reasons—even if there is an answer that I'm looking for, I can't filter it from people who are just throwing generic tag-words around.
I'm not interested in answers that are telling me how to get around that; I can do that myself:
Using Bean Scripting Framework (BSF)
File sample.py (in py folder) contents:
def factorial(n):
return reduce(lambda x, y:x * y, range(1, n + 1))
And Java code:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("jython");
engine.eval(new FileReader("py" + java.io.File.separator + "sample.py"));
System.out.println(engine.eval("factorial(932)"));
Using designed bridges like JLink
This is equivalent to:
String expr = "N[Integrate[E^(2 y^5)/(2 x^3), {x, 4, 7}, {y, 2, 3}]]";
System.out.println(MM.Eval(expr));
//Output: 1.5187560850359461*^206 + 4.2210685420287355*^190*I
Other methods
Using Dijkstras shunting-yard algorithm or alike and writing an expression evaluator from scratch.
Using complex regex and string manipulations with delegates and HashMultimaps.
Using Java Expressions Library
Using Java Expression Language
Using JRE compliant scripting language like BeanShell.
Using the Java Assembler and approach below or direct bytecode manipulation like Javaassist.
Using the Java Compiler API and reflections.
Using Runtime.getRuntime().exec as root
"eval" is only available in scripting languages, because it uses the same interpreter that runs the rest of the code; in such languages the feature is free and well integrated, as in scripting environment it makes little difference if you run a string or a "real" function.
In copiled languages, adding "eval" would mean bundling the whole compiler - which would defy the purpose of compiling. No compiled language I know (even dynamic ones, like ActionScrip3) has eval.
Incidentally, the easiest way to eval in Java is the one you forgot to mention: JRE 1.6 comes with Javascript engine, so you can eval any Javascript in two lines of code. You could even argue that the presuposition of your question is false. Java 1.6 bundles a very advanced expression evaluator.
As Daniel points out there is at least one limitation that eval-solutions face in java. The php eval for example executes the code as if it was part of the surrounding method with complete access to local variables, this is not possible to do in standard java. Without this feature eval alternatives require a lot more work and verbosity, which makes them a lot less attractive for "quick" and "easy" solutions.
eval() is mostly part of interpreted languages where the names of local variables and code structure(scopes) are available at runtime, making it possible to "insert" new code. Java bytecode no longer contains this information leaving eval() alternatives unable to map access to local variables. (Note: I ignore debug information as no program should rely on it and it may not be present)
An example
int i = 0;
eval("i = 1");
System.out.println(i);
required pseudocode for java
context.put("i",new Integer(0));
eval(context,"i = 1");
System.out.println(context.get("i"));
This looks nice for one variable used in the eval, try it for 10 in a longer method and you get 20 additional lines for variable access and the one or other runtime error if you forget one.
Because evaluation of arbitrary Java expressions depends on the context of it, of variable scopes etc.
If you need some kind of variable expression, just use the scripting framework, and badamm! you have lots of different kinds of expression evaluation. Just take one kind like JavaScript as a default, and there is your eval()!
Enterprisy as Java is, you are not constrained to one choice.
But even worse seems being notified that you can't have it.
I think you are misunderstanding what (most of) those articles are saying. Clearly, there are many ways to do expression evaluation in a Java application. They haven't always been available, but at least some of them have been around for a long time.
I think what people are trying to say is that expression evaluation is not available as native (i.e. as an intrinsic part of Java or the standard libraries) and is unlikely to be added for a number of good reasons. For example:
Native eval would have significant security issues if used in the wrong place. (And it does for other languages; e.g. you shouldn't use eval in Javascript to read JSON because it can be a route for injecting bad stuff into the user's browser.)
Native eval would have significant performance issues, compared with compiled Java code. We are talking of 100 to 10,000 times slower, depending on the implementation techniques and the amount of caching of "compiled" eval expressions.
Native eval would introduce a whole stack of reliability issues ... much as overuse / misuse of type casting and reflection to.
Native eval is "not Java". Java is designed to be a primarily static programming language.
and of course ...
There are other ways to do this, including all of the implementation approaches that you listed. The Java SE platform is not in the business of providing every possible library that anyone could possibly want. (JRE downloads are big enough already.)
For these reasons, and probably others as well, the Java language designers have decided not to support expression evaluation natively in Java SE. (Even so, some expression support has officially made it into Java EE; e.g. in the form of JSP Expression Language. The classes are in the javax.el package ... or javax.servlet.jsp.el for an older / deprecated version.)
I think you already put the solution to your answer - bundle the BeanShell jar with your application (or lobby for it to be included in the JRE sometime), and you have your Java expression evaluator. It will still need a Binding of the input variables, though.
(What I'm more curious about: How does sandboxing of such a script/expression work? I don't want my web users to execute dangerous code in my server.)