Is it possible to create XML nodes using XPath?
Assume i got the following XML:
<data>
<someValue1></someValue2>
<someValue2></someValue2>
<someArray>
<val></val>
<val></val>
<val></val>
</someArray>
</data>
What I am trying to do is getting a node inside the XML using XPath (e.g. /data/someValue1) and setting the value of the node. This is of course easy to achieve with any language and framework supporting XML + XPath.
But when my XPath expression is pointing to a non existing node I want to somehow create this node. Even if the XPath expression is more complex (e.g. /data/someArray/val[5]).
At best this automatic node creation should be supported by some library. Is there an easy way for what I am trying to achieve? Currently I am using C++ with Qt and the QXmlQuery class.
Is it possible to create XML nodes using XPath?
No, it isn't. XPath can only select existing nodes.
If you want to create new nodes, you need XSLT or XQuery.
But even then, creating a node that satisfies a given path like /a/b/c/foo[5] is non-trivial, and not something that the languages can do automatically.
Related
I am pretty new to IIB. I am creating a mediation service on IBM Integration Bus 10. First node is SOAP node and second node is an XSL transform. Complete flow of the service
XSL transform is working fine with my SOAP input when I test it in a different tool. But it fails here when I am testing from soapui. After Transform node, I am getting the output without XML tags (all values appended in single string)
I have no clue why it is happening. Any help is well appreciated.
I am getting the output without xml tags (all values appended in single string)
IIB will not assume that the output of an XSLTransform node is XML. An XSL stylesheet can output formatted text. So you must set the 'Domain' property in the 'Output message parsing' section of the XSLTransform node. Set it to XMLNSC, obviously.
First node is SOAP node and second node is xsl transform
Is there a particular reason why you have chosen to use the XSLTransform node? A Mapping node or a Compute node will perform better, and will be more maintainable than XSL (unless you are doing some genuinely complex transformations in XSL).
Maybe you have to see what is the version of the XSLT. If it is 2.0, XSL Transform Node is not supporting it. Try to rewrite it in XSLT version 1.0.
I want to try a tag not closed with xpath like this:
<figure class="img"><img class="immagine-in-linea-senza-cornice" width="16%" src="images/schema_1_fmt.jpeg" alt=""/>
I want to close the tag with a xslt transformation.
XPath does not work directly on the input document, but on an abstract, tree-like representation of the document (e.g. XDM or DOM). In this model, opening and closing tags of an element are not represented at all. Instead, an element appears as a single entity in the tree.
Therefore, manipulating < and /> is completely out of the question for languages like XPath, because the concept of opening and closing tags is simply not implemented. I would argue that this abstraction is an advantage of the models, though.
Also, XSLT transformations normally take as input XML documents. If your document has unclosed elements, it will be rejected by any application that is only prepared to process XML.
In short, fix the XML document with a language other than the combination of XSLT and XPath (see e.g. here), and think about XSLT as soon as you have well-formed XML as input.
I have to extract some records from a dynamically generated xml document whose hierarchy will be of a pre-defined format but the depth of the hierarchy will not be known. I am working in a .net framework and i know that we can use .net methods from xsl and that we need to use a recursive function in this situation in conventional programming paradigm. but i dont know how to work round it using pure xsl, which is what i need to do in this particular case.
Use // before node names example:
<xsl:template match="//temp">
<!--do whatever you want-->
</xsl:template>
This will apply to all the elements that are having name temp appearing in any hierarchy ..
I need to include an XSLT that exists in 2 variants, depending on a param value.
However, it's seems to be not possible to write an expression in the href attribute of the xsl:include element. My last trial looks like that:
< xsl:param name="ml-fmt" select="mono"/>
...
< xsl:include href="{$ml-fmt}/format.xsl"/>
The XSLT engine used is Saxon 9.2.0.6
Have anybody an idea about how I could do something close to that ?
As Dimitre has said you can't do it, but you can generate the XSLT file from scratch or slightly modify an existing XSLT file by inserting the node in the code preparing the transformation.
You can't.
If you know all possible xslt stylesheet modules to be included, you could use the xsl:use-when attribute in order to selectively include only some of them. However, xsl:use-when has its own limitations. To quote the XSLT 2.0 Spec:
"Any element in the XSLT namespace may have a use-when attribute whose value is an XPath expression that can be evaluated statically".
There is a way to achieve dynamic inclusion, but it requires some non-XSLT initialization:
The code (think C# or Java or ... your programming language) that invokes the transformation, can edit the DOM of the loaded (as XML) XSLT stylesheet and can set the value of the href attribute of any <xsl:import> element to the desired URL.
is it at all possible to 'pre-proccess' in XSLT?
with preprocessing i mean updating the (in memory representation) of the source tree.
is this possible, or do i need to do multiple transforms for it.
use case:
we have Docbook reference manuals for out clients but for certain clients these need different 'skins' (different images etc). so what i was hoping to do is transform the image fileref path depending on a parameter. then apply the rest of the normal Docbook XSL templates.
Expanding on Eamon's answer...
In the case of either XSLT 1.0 or 2.0, you'd start by putting the intermediate (pre-processed) result in an <xsl:variable> element, declared either globally (top-level) or locally (inside a template).
<xsl:variable name="intermediate-result">
<!-- code to create pre-processed result, e.g.: -->
<xsl:apply-templates mode="pre-process"/>
</xsl:variable>
In XSLT 2.0, the value of the $intermediate-result variable is a node sequence consisting of one document node (was called "root node" in XSLT/XPath 1.0). You can access and use it just as you would any other variable, e.g., select="$intermediate-result/doc"
But in XSLT 1.0, the value of the $intermediate-result variable is not a first-class node-set. Instead, it's something called a "result tree fragment". It behaves like a node-set containing one root node, but you're restricted in how you can use it. You can copy it and get its string-value, but you can't drill down using XPath, as in select="$intermediate-result/doc". To do that, you must first convert it to a first-class node-set using your processor's node-set() extension function. In Saxon 6.5, libxslt, and 4xslt, you can use exsl:node-set() (as in Eamon's answer). In MSXML, you'd need to use msxsl:node-set(), where xmlns:msxsl="urn:schemas-microsoft-com:xslt", and in Xalan, I believe it's called xalan:nodeset() (without the hyphen, but you'll have to Google for the namespace URI). For example: select="exsl:node-set($intermediate-result)/doc"
XSLT 2.0 simply abolished the result tree fragment, making node-set() unnecessary.
This is not possible with standards compliant XSLT 1.0. It is possible in every actual implementation I've used, however. The extensions with which to do that differ by engine, however. It is also possible in standard XSLT 2.0 (which is in any case much easier to work with - so if you can, just use that).
If your xslt processor supports EXSLT, the exsl:node-set() function does what you're looking for. msxml has an identically named extension function as well (but with a different namespace uri, the functions are unfortunately not trivially compatible).
Since you are trying to generate slightly different output from the same DocBook XML source, you might want to look into the "profiling" (conditional markup) support in DocBook XSL stylesheets. See Chapter 26 in DocBook XSL: The Complete Guide by Bob Stayton:
Profiling is the term used in DocBook
to describe conditional text.
Conditional text means you can create
a single XML document with some
elements marked as conditional. When
you process such a document, you can
specify which conditions apply for
that version of output, and the
stylesheet will include or exclude the
marked text to satisfy the conditions.
This feature is useful when you need
to produce more than one version of a
document, and the versions differ in
minor ways.
For example, to use different images for, say, Windows and Mac versions of the same document, you might have a DocBook XML fragment like this:
<figure>
<title>The Foo dialog</title>
<mediaobject>
<imageobject os="windows">
<imagedata fileref="screenshots/windows/foo.png"/>
</imageobject>
<imageobject os="mac">
<imagedata fileref="screenshots/mac/foo.png"/>
</imageobject>
</mediaobject>
</figure>
Then, you would use the profiling-enabled versions of the DocBook XSL stylesheets with the profile.os parameter set to windows or mac.
Maybe you should use XSLT "OOP" methods here. Put all the common templates to all clients in a stylesheet, and create an stylesheet for each client with specific templates overriding common ones. Import the common stylesheet within the specific ones with xsl:import, and you'll do only one processing by calling the stylesheet corresponding to a client.