Can you disable output of the main output file in Saxon/XSLT3? - xslt

I am using XSLT3 as provided in Saxon to convert a single input XML file to a set of output files. All these output files are conceptually equivalent. Each output file is declared via the result-document directive, as explained on https://www.w3.org/TR/2007/REC-xslt20-20070123/#element-result-document.
In this case, I don't need any main output, but Saxon is still creating such output file. Is it somehow possible to disable the main output in XSLT3 or Saxon?
I could use result-document for all desired output files, except the last one, and just use the main output for that one - but that feels odd.

It's a good question. XSLT 2.0 had a very complicated rule (in ยง2.4): An implicit result tree is also created when the result sequence is empty, provided that no xsl:result-document instruction has been evaluated during the course of the transformation. In this situation the implicit result tree will consist of a document node with no children.
Interpreting "creating a result tree" as meaning that the corresponding serialised output file is written to filestore, this means that when the principal result tree is empty, the corresponding output file is written if and only if there are no secondary output files. Which is (I think) the effect that you are asking for.
This rule became increasingly unwieldy in XSLT 3.0 because of the greatly extended ways of invoking a stylesheet (e.g by calling an initial public function), and it was therefore dropped; and Saxon followed suit.
You can certainly avoid the file being written by supplying a result or destination that discards it rather than writing it to filestore (for example, in s9api, an XdmDestination). Achieving the same thing from the command line is not so easy; in fact, I'm not sure it can be done without writing some Java or C# code somewhere.

Related

How to document test cases of a program with complex input

I need to document tests that execute a program which takes a xml file as input and then generates multiple .c and .xml files as output.
The existing 300 tests are implemented as JUnit test cases and I started documenting them with doxygen.
The documentation should help to save time when it comes to the questions:
Which test cases have to be modified when a specific feature is modified?
Are all features of the program tested in at least one test case?
My first ideas was to use the classification tree method. The result would look like this example picture:
The program to test uses only a few boolean parameters but also a XML file which is the main input. This XML file contains different lists of nodes and a lot of invariants have to be checked by the program when generating the output .c and .xml files. As part of the tests the input XML file and the generated files are also parsed and compared.
To apply the classification tree method equivalence classes have to be found. In my case all possible contents of the input XML file have to be classified.
How could a structured way of working through all of these possible XML nodes look like? This seems to be a complicated task and I want to proceed in an efficient way.
Maybe using the classification tree method is also not the best choice for this task. Are there other/better options?

Qt5.5 XML processing using QDom

I'm using the QDom classes to process an XML file, I want the attributes to be processed in the order they are defined in the XML file, this is important. However it seems the order of the attributes in the 'QDomNamedNodeMap' is different.
Is there any way to ensure the order is as defined in the XML file?
As far as I know, you can't rely on order of attributes in XML, by specifications. This could be the reason your library read them in a different order that the literal one. Even if you find a way, you should not trust it: what about if someone else generates the XML to feed your program? See here more about the specifications.
Maybe a change in the design can help you: what about nesting some nodes? Nesting nodes sequence is deterministic.
I've written my own classes that read the file and process the nodes and attributes, as per my requirement the attributes are kept in the same order they are presented in the file.

Reading Environment Variables in an XSLT Stylesheet with Saxon

I'm trying to generate an XML file with the my machine's hostname in some arbitrary element or attribute, e.g.
<hostname>myHostname</hostname>
I'm using Saxon 9.2. I can think of three ways to do this:
Read and parse /etc/sysconfig/network (I'm using Fedora)
Read the environment variable (as in $ echo $HOSTNAME)
Pass the hostname to saxon and then use somehow dereference a variable (not sure if this is possible)
Are any of these possible? I think the first option is most likely to work, but I think the other two options will produce less verbose XSLT.
I also have a related question:
Currently, I have an XSLT and source XML file that generates a bunch of XML files, it works like I expect it to. Is there anyway I can selectively generate one file per host? That is, I want to say 'if the hostname is myHostName then generate the XML file for myHostName, if the hostname is myOtherHostName then generate the XML file for myOtherHostName'.
I ask this because I'm trying to configure a large number of machines and if I could drop an XSLT and XML file on each and then call the same command on every machine and hten get the right XML on each it would be really convienent.
You should pass a parameter to your xslt when "calling" it. I think this is the most robust solution.
So at the top of your stylesheet you would have something like :
<xsl:param name="hostName"/>
Then you can use it in your .xslt via the usual notation : $hostName etc.
You just then need to pass those parameters when calling the xslt processor. Depending on how you use it this may vary.
You can generate an XML file containing all needed parameters, then you can either pass it as parameter to the transformation (refer to the code samples to see examples of how this is done with Saxon).
Here is a link that can help: https://www.saxonica.com/html/documentation/javadoc/net/sf/saxon/expr/instruct/GlobalParameterSet.html
Or simpler, save this XML file in the file system and just pass as parameter to the transformation the file path and name.
Then inside the transformation, use the standard XSLT function document() to load the XML document that contains the parameters.
Even further simplification is possible, if this file can be stored at a location that has exactly the same path on all machines. Then this avoids the need to pass this filepath as parameter to the transformation.
There are many possible ways of doing this: passing in parameters, reading the configuration file using the unparsed-text() function, calling an extension function.
But perhaps the most direct way is that Saxon 9.3 implements the new XPath 3.0 function get-environment-variable(). Support for XPath 3.0 requires Saxon-PE or higher.
(XPath 3.0 is of course still a draft and subject to change. In fact it has changed since Saxon 9.3 was released - the function has been renamed environment-variable()).

How can I identify line numbers in XSLT input or from XPath?

I am processing XML files using an XSLT stylsheet and wish to report the input line number when a given template is triggered. I can use a DOM (e.g. XOM in Java) which supports a SAX parser so maybe can use a Locator.
Alternatively the XSLT generates an Xpath which could be applied to the original document and so, at least for a human, can lead to the particular line.
(The actual application is to detect error conditions in the XML, which are searched for using XSLT)
Saxon has an extension for this. You can set an option when building the source tree to maintain line number information (e.g. -l on the command line), and if this was set, you can use the extension function saxon:line-number() to get the line number associated with an element node in the tree.

XSLT getting character count of transformed XML

I am creating some XML from an XSLT
the XML after transformation looks a little like...
<root><one><two>dfd</two></one></root>
I need to get a character count for the output (in this case would be 38).
I tried putting the whole lot in a variable then doing a string-length($vVariable) but this only brings back 3 (for the 'dfd' it excludes the characters of the tags)
This is going to be very difficult to do in straight XSLT, since it's internal data model doesn't see XML elements as strings. Although your particular example is very simple, there are multiple valid ways to serialize the same XML into text, especially when you get into namespaces.
Your best bet may be to send the result of your transformation to another tool. If you're running the XSLT processor from the command line, you could use a tool like the linux command "wc"). If you're calling XSLT from within a larger program, you could use that language's built-in string-length functionality.