XSLT: xsltApplyStylesheet returns null - libxslt

I've a xml and xsl file. The output from xsl is just a text i.e if some conditions fail, the result is just a description of the failure. If all the conditions pass, the result is null. If I run this in xsltproc, it works fine.
However, If I run this using libxslt using function xsltApplyStylesheet, I see empty result. The input xml to xsltApplyStylesheet is created dynamically in the code. The xsl file is read using xsltParseStylesheetFile. (I used xmlDocDumpFormatMemory of both the xml and the output of xsltParseStylesheetFile->doc, both seems to be fine). I tried xsltSaveResultToString after ApplyStylesheet, it doesn't work as well.
What could be possible issue here?
Code Snippet:
xmldoc = xmlNewDoc(BAD_CAST "1.0");
c = xmlNewNode(NULL, BAD_CAST "Company");
xmlAddChild(c, node); //node is another child in XML
xmlAddChild(c, d); //d is another child in xml
xmlDocSetRootElement(xmldoc, c);
.....
xsl = xsltParseStylesheetFile("xsl.file");
....
output = xsltApplyStylesheet(xsl, xmldoc, NULL);
....
//output has just "<?xml version="1.0"?>"
TIA and appreciate your help!

Use xmlDocDumpMemory to save the file as in a similar question before applying the stylesheet, and see if that works.
References
XMLSoft FAQ
how to save XML to a file (filename.xml) using libxml2 ?
Android - ArchWiki

Related

How to replace the first few bytes of a file in Ruby without opening the whole file?

I have a 30MB XML file that contains some gibberish in the beginning, and so typically I have to remove that in order for Nokogiri to be able to parse the XML document properly.
Here's what I currently have:
contents = File.open(file_path).read
if contents[0..123].include? 'authenticate_response'
fixed_contents = File.open(file_path).read[123..-1]
File.open(file_path, 'w') { |f| f.write(fixed_contents) }
end
However, this actually causes the ruby script to open up the large XML file twice. Once to read the first 123 characters, and another time to read everything but the first 123 characters.
To solve the first issue, I was able to accomplish this:
contents = File.open(file_path).read(123)
However, now I need to remove these characters from the file without reading the entire file. How can I "trim" the beginning of this file without having to open the entire thing in memory?
You can open the file once, then read and check the "garbage" and finally pass the opened file directly to nokogiri for parsing. That way, you only need read the file once and don't need to write it at all.
File.open(file_path) do |xml_file|
if xml_file.read(123).include? 'authenticate_response'
# header found, nothing to do
else
# no header found. We rewind and let nokogiri parse the whole file
xml_file.rewind
end
xml = Nokogiri::XML.parse(xml_file)
# Now to whatever you want with the parsed XML document
end
Please refer to the documentation of IO#read, IO#rewind and Nokigiri::XML::Document.parse for details about those methods.

How can I add my own code to JAVA generated classes from proto file?

I'm using protobuf and I'm generating JAVA classes from the following proto file.
syntax = "proto3";
enum Greeting {
NONE = 0;
MR = 1;
MRS = 2;
MISS = 3;
}
message Hello {
Greeting greeting = 1;
string name = 2;
}
message Bye {
string name = 1;
}
option java_multiple_files = true;
Now I need to add some code to the generated files and I found that is possible using a custom plugin (https://developers.google.com/protocol-buffers/docs/reference/java-generated#plugins). I'm trying to generate that plugin in Java, something like this.
public class Test {
PluginProtos.CodeGeneratorResponse.getDefaultInstance();
/* Code to get generated files from java_out and use the insertion points */
codeGeneratorResponse.writeTo(System.out);
}
And then I run
protoc --java_out=./classes --plugin=protoc-gen-demo=my-plugin --demo_out=. example.proto
The problem is that on my Test.java main method I don't know how to get access to the files created by the option --java_out so that I can use their insertion points. Currently the CodeGeneratorResponse for the default instance is empty (no files).
Does anybody know how can I get the CodeGeneratorResponse from the --java_out so that I can add more code to the generated classes?
Thanks in advance.
I recently struggled with this as well and wasn't able to find a good answer. I finally figured it out after staring at the comments within the CodeGeneratorResponse message for a while.
What threw me off at first was that I was thinking of plugins as a pipeline, where the output from one feeds into the next. However, each plugin gets the exact same input (the parsed .proto files expressed via CodeGeneratorRequest messages), and all the generated code from the plugins (including the built-in ones) gets combined into the output file. However, plugins may modify the output from the previous plugins, which is what insertion points are designed for.
Specifically to your question, you would add a file to the response with the name field getting set to the name of the generated Java file, the insertion_point field getting set to the name of the insertion point at which you want to add code, and the content field getting set to the code you want inserted at that point.
I found this article helpful in creating a simple plugin (in this case in python). As a simple test, I modified the generate_code function from that article to look like this:
def generate_code(request, response):
for proto_file in request.proto_file:
f = response.file.add()
f.name = "Test.java"
f.insertion_point = "outer_class_scope"
f.content = "// Inserting a comment as a test"
Then I ran protoc with the plugin:
$ cat test.proto
syntax = "proto3";
message MyMsg {
int32 num = 1;
}
$ protoc --plugin=protoc-gen-sample=sample_proto_gen.py --java_out=. --sample_out=. test.proto
$ tail -n3 Test.java
// Inserting a comment as a test
// ##protoc_insertion_point(outer_class_scope)
}
Your plugin just needs to be some executable which reads a CodeGeneratorRequest message from stdin and writes a CodeGeneratorResponse message to stdout, so could certainly be written in Java instead. I just chose python as I'm generally more comfortable with it and found this simple example.
As a reference, here's a plugin I wrote for generating code based on custom protobuf options.
I have made a custom python plugin.
To run my plugin i use the command below:
protoc --plugin=protoc-gen-custom=my_plugin_executable_file --custom_out=./build test.proto
So i think that, you have to generate an executable file from your .java file and use it in your command.

Write JDBC query results to CSV file?

I would like to setup a test plan to execute a query and write the results to a csv file.
Following the advice from this question:
https://sqa.stackexchange.com/questions/26456/write-jdbc-request-results-to-csv-file
I have setup my test plan. It runs without issue, but a foo.csv file is not created.
this is the code in the JSR223 preprocessor:
resultSet = vars.getObject("resultSet");
StringBuilder result = new StringBuilder();
for (Object row : resultSet ) {
iter = row.entrySet().iterator();
while (iter.hasNext()) {
pair = iter.next();
result.append(pair.getValue());
result.append(",");
}
result.append(System.getProperty("line.separator"));
}
org.apache.commons.io.FileUtils.writeStringToFile(new File("foo.csv"), result.toString(), "UTF-8");
The file is being written in current working directory, you can locate where JMeter written it by running the following command in the Terminal application:
find / -type f -name 'foo.csv'
You can also amend the last line of code in order to explicitly specify full path to the CSV file like:
org.apache.commons.io.FileUtils.writeStringToFile(new File("/Users/aoppenheim/Desktop/foo.csv"), result.toString(), "UTF-8");
Also I would suggest switching "Language" to groovy as java assumes using Beanshell interpreter and it might become a performance bottleneck in case of high loads. See Apache Groovy - Why and How You Should Use It guide for more details.
This was actually working, the csv file was just not being written where I expected. I added this to find the file:
log.info(System.getProperty("user.dir"));

Finding XML text values with spaces using Nokogiri

How to find the Fetus Summary node using xpath?
<container flag="SEPARATE">
<relationship>CONTAINS</relationship>
<concept>
<value>125008</value>
<scheme>
<designator>DCM</designator>
</scheme>
<meaning>Fetus Summary</meaning>
</concept>
</container>
This doesn't work:
xml.xpath( '//*[.="Fetus Summary"]' )
But similar code does, when using text values without spaces. Can someone please help?
Try to use normalize-space() function, e.g.:
//*[normalize-space(.)="Fetus Summary"]
Your original code works just fine with the XML that you have shared:
require 'nokogiri'
doc = Nokogiri.XML '
<container flag="SEPARATE">
<relationship>CONTAINS</relationship>
<concept>
<value>125008</value>
<scheme>
<designator>DCM</designator>
</scheme>
<meaning>Fetus Summary</meaning>
</concept>
</container>
'
puts doc.at_xpath( '//*[.="Fetus Summary"]' )
#=> <meaning>Fetus Summary</meaning>
This works even if you have the XML declaration <?xml version="1.0" encoding="ISO-8859-1"?> at the start of the document.
My guess is that your document has whitespace characters that look like spaces or tabs but are not. From where are you getting your XML? (Over the Internet using open-uri, or from a file?) Can you please post the result of p my_xml_string to your question, which will encode any complex characters?

How do I use Nokogiri to parse a single file with multiple XML documents in it?

I have a single file that contains multiple concatenated XML files like so:
<?xml version ... ?>
<!DOCTYPE ... >
...
<?xml version ... ?>
<!DOCTYPE ... >
...
<?xml version ... ?>
<!DOCTYPE ... >
...
Is there any way to parse the file as is, using Nokogiri, as opposed to slicing the file up?
You need to slice it into individual documents, but that is an easy thing to do.
Ruby's String.split method makes it easy. For instance if variable foo contains the text, then foo.split("<?xml version ... ?>\n") will return an array you can loop over:
foo.split("<?xml version ... ?>\n")
[
[0] "",
[1] "<!DOCTYPE ... >\n...\n",
[2] "<!DOCTYPE ... >\n...\n",
[3] "<!DOCTYPE ... >\n..."
]
Parse each of those chunks and you'll be on your way. You might need to prepend the XML DECL statement to make Nokogiri happy, but I think it'll do OK without it.
This wouldn't be a valid XML file, so you can't parse it all in one go. But you may be able to create a class that inherits from File, and has the smarts to return end-of-file when you get to the end of each XML document. With that, you should be able to open your file once, but you would still make multiple calls to your XML parser.
If the XML fragments are not very large, it may be best to slurp a fragment at at time into a string variable (perhaps using regexp), and parse that.

Resources