I'm trying to print all root to leaf path using recursion, but I'm clueless
I don't know how to approach it, I'm completely stuck
<node id="N1">
<node id="N1">
<node id="N1"></node>
<node id="N2"></node>
<node id="N3"></node>
</node>
</node>
desired output :
N1 N1 N1
N1 N1 N2
N1 N1 N3
A simple
<xsl:value-of select="//node[not(*)]/string-join(ancestor-or-self::node/#id, ' ')" separator="
"/>
should do, without any need for recursion.
Related
I would like to combine all Node2 values into a single Node2. However, if the combined string is greater than 20 characters, I want to append the combined string to Node1 and truncate Node2 to only 20 characters.
<Parent>
<Node1>Some Text</Node1>
<Node2>Some Name1</Node2>
<Node2>Some Name2</Node2>
<Node2>Some Name3</Node2>
<Node2>Some Name4</Node2>
<Node2>Some Name5</Node2>
</Parent>
The desired result is:
<Parent>
<Node1>Some Text; Node2: Some Name1, Some Name2, Some Name3, Some Name4, Some Name5</Node1>
<Node2>Some Name1, Some Nam</Node2>
</Parent>
Try the following XSLT-2.0 solution:
<xsl:template match="/Parent">
<xsl:copy>
<xsl:copy-of select="#*" />
<xsl:variable name="n2">
<xsl:value-of select="Node2" separator=", "/>
</xsl:variable>
<Node1><xsl:value-of select="Node1, if (string-length($n2) > 20) then concat('; Node2: ',$n2) else ''" separator=""/></Node1>
<Node2><xsl:value-of select="substring($n2,1,20)" /></Node2>
</xsl:copy>
</xsl:template>
Output is:
<?xml version="1.0" encoding="UTF-8"?>
<Parent>
<Node1>Some Text; Node2: Some Name1, Some Name2, Some Name3, Some Name4, Some Name5</Node1>
<Node2>Some Name1, Some Nam</Node2>
</Parent>
I want to change "A" in Apple, in key which value is 1 to "D", in this code 2 items should be replaced. I tried something like this, but nothing happens.
<C>
<B>
<Key value="1">
<Apple>A</Apple>
</Key>
<Key value="2">
<Apple>A</Apple>
</Key>
<Key value="3">
<Apple>A</Apple>
</Key>
<Key value="1">
<Apple>A</Apple>
</Key>
</B>
</C>
Qt:
QDomNodeList roots = doc.elementsByTagName("Key");
for (int i = 0; i < roots.size(); ++i) {
QDomElement domElement = roots.at(i).toElement();
QDomAttr attribute = domElement.attributeNode("value");
if (attribute.value() == "1") {
domElement.firstChild().setNodeValue("D");
}
In your code the domElement.firstChild() refers to the <Apple> element node, not to its content. The value inside the <Apple> is also a node (text node), that is why it is located one level deeper in the DOM hierarchy:
domElement — <Key>
domElement.firstChild() — <Apple>
domElement.firstChild().firstChild() — A
So you will also have to get the first child of the <Apple> element node:
domElement.firstChild().firstChild().setNodeValue("D");
Maybe:
if (attribute.value() == "1")
Im trying to create a function in javascript in xsl which accepts multiple in-parameters. I can not get it to work and get the following error:
Code: 0x80020009
Microsoft JScript runtime error
Wrong number of arguments or invalid property assignment
line = 37, col = 2 (line is offset from the start of the script block).
Error returned from property or method call.
The function looks as follows:
<msxsl:script language="JavaScript" implements-prefix="jsfuncs">
<![CDATA[
function getLineLength (x1,x2,y1,y2)
{
var xVector = x2 - x1;
var yVector = y2 - y1;
var output = Math.sqrt(raised2(xVector)+raised2(yVector));
return output;
}
]]>
</msxsl:script>
The calling code looks as follows:
<xsl:value-of select="jsfuncs:getLineLength($x1,$x2,$y1,$y2)"/>
x1,x2... are variables set earlier and they are correct. I can get everything to work when I post-process the values to one parameter. Is it at all possible to pass multiple parameters in xslt to Javascript? The engine in use is msxml 3.0.
Here is an example passing in four parameters:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="ms mf"
version="1.0">
<ms:script language="JScript" implements-prefix="mf">
function test(a, b, c, d) {
return a + ":" + b + ":" + c + ":" + d;
}
</ms:script>
<xsl:template match="/">
<xsl:value-of select="mf:test(1, 2, 3, 'foo')"/>
<br/>
<xsl:variable name="item" select="root/item"/>
<xsl:value-of select="mf:test(string($item/#a), string($item/#b), string($item/#c), string($item/#d))"/>
</xsl:template>
</xsl:stylesheet>
As you can see, when wanting to pass in a node to a function expecting a primitive value I would recommend to make sure to convert it on the XSLT side to a primitive value first, as done in mf:test(string($item/#a), string($item/#b), string($item/#c), string($item/#d)), as otherwise the function will get a node-set represented by some selection interface that you would need to iterate first.
The sample works fine for me with MSXML 3 and outputs 1:2:3:foo<br />1:2:3:whatever when run against an input sample with
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item a="1" b="2" c="3" d="whatever"/>
</root>
I have a problem converting XSLT 2.0 to XSLT 3.0. I want to use the streaming capability of XSLT 3.0. I am struggling with using the <xsl:stream> and <xsl:mode> tags as XSLT 3.0 has several restrictions. For using XSLT 3.0 streaming capabilities, following restrictions are faced:
“Sibling nodes and ancestor sibling are not reachable”.
"You can visit child nodes only once"
"You have access only to the current element attributes and namespace declaration"
How can I overcome these restrictions? Can anyone please help me?
<?xml version="1.0" encoding="UTF-8">
<xsl:stream href="SampleInput3_0.xml">
<xsl:for-each select="copy-of(ns0:ORM_O01/ns0:ORM_O01.PATIENT/ns0:PID)">
<Patient>
<ucfd:Name>
<xsl:variable name="varFirst_Name" as="node()" select="ns0:PID.5/ns0:XPN.2[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]" />
<xsl:variable name="varLast_Name" as="node()" select="ns0:XPN.1/ns0:FN.1[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]" />
<xsl:attribute name="value" namespace="" select="concat(string($varFirst_Name), string(varLast_Name))" />
</ucfd:Name>
<ucfd:FirstName value="{ns0:PID.5/ns0:XPN.2[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:LastName value="{ns0:PID.5/ns0:XPN.1/ns0:FN.1}" />
<ucfd:MiddleName value="{ns0:PID.5/ns0:XPN.3[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Prefix value="{ns0:PID.5/ns0:XPN.5[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Suffix value="{ns0:PID.5/ns0:XPN.4[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Identification>
<ucfd:TaxIdentifier>
<ucfd:Type value="{ns0:PID.18/ns0:CX.5[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Identifier value="{ns0:PID.18/ns0:CX.1}" />
</ucfd:TaxIdentifier>
</ucfd:Identification>
<xsl:for-each select="ns0:PID.11">
<ucfd:Address>
<xsl:if test="exists(#Type)">
<ucfd:Type value="{ns0:XAD.7[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
</xsl:if>
<ucfd:City value="{ns0:XAD.3[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:State value="{ns0:XAD.4[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:PostalCode value="{ns0:XAD.5[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Country value="{ns0:XAD.6[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:County value="{ns0:XAD.9[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
</ucfd:Address>
</xsl:for-each>
<ucfd:Contact>
<ucfd:Role value="{ns0:PID.13/ns0:XTN.2[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Type value="{ns0:PID.13/ns0:XTN.3[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<xsl:for-each select="ns0:PID.13">
<!--<xsl:variable name="var9_current" as="node()" select="."/>-->
<ucfd:CommunicationNumber>
<xsl:if test="exists(#Type)">
<ucfd:Type>
<xsl:sequence select="()" />
</ucfd:Type>
</xsl:if>
<ucfd:Identifier>
<!--<xsl:variable name="var8_current" as="node()" select="ns0:XTN.5[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]"/>
<xsl:variable name="var7_current" as="node()" select="ns0:XTN.6[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]"/>
<xsl:variable name="var6_current" as="node()" select="ns0:XTN.7[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]"/>
<xsl:variable name="var5_current" as="node()" select="ns0:XTN.8[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]"/>
<xsl:variable name="var4_current" as="node()" select="ns0:XTN.10[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]"/>
<xsl:variable name="var3_current" as="node()" select="ns0:XTN.11[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]"/>
<xsl:attribute name="value" namespace="" select="concat(concat(concat(concat(concat(string($var8_current), string($var7_current)), string($var6_current)), string($var5_current)), string($var4_current)), string($var3_current))"/> -->
</ucfd:Identifier>
</ucfd:CommunicationNumber>
</xsl:for-each>
</ucfd:Contact>
<ucfd:Demographics>
<ucfd:BirthDate>
<xsl:sequence select="()" />
</ucfd:BirthDate>
<ucfd:BirthSequenceNumber>
<xsl:for-each select="ns0:ORM_O01/ns0:ORM_O01.PATIENT/ns0:PID/ns0:PID.25">
<xsl:attribute name="value" namespace="">
<xsl:if test="not((translate(string(#xsi:nil), 'true ', '1') = '1'))">
<xsl:sequence select="xs:string(xs:integer(string(.)))" />
</xsl:if>
</xsl:attribute>
</xsl:for-each>
</ucfd:BirthSequenceNumber>
<ucfd:DeathDate>
<xsl:sequence select="()" />
</ucfd:DeathDate>
<ucfd:Gender value="ns0:PID.8[not((translate(string(#xsi:nil), 'true ', '1') = '1'))]" />
<ucfd:MaritalStatus value="{ns0:PID.16/ns0:CE_0002.1[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:CitizenshipStatus value="{ns0:PID.26[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:RaceOrEthnicity>
<ucfd:Race value="{ns0:PID.10/ns0:CE_0005.1[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
</ucfd:RaceOrEthnicity>
<ucfd:Religion value="{ns0:PID.17/ns0:CE_0006.2[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
</ucfd:Demographics>
<ucfd:Language>
<ucfd:LanguageCode value="{ns0:PID.15/ns0:CE_0296.1[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:Description value="{ns0:PID.15/ns0:CE_0296.2[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
<ucfd:UseIndicator value="{ns0:PID.15/ns0:CE_0296.3[not(translate(#xsi:nil, 'true ', '1') = '1')]}" />
</ucfd:Language>
</Patient>
</xsl:for-each>
</xsl:stream>
</MemberRecord>
</xsl:template>
</xsl:stylesheet>
I think you should follow the approach in http://saxonica.com/documentation/index.html#!sourcedocs/streaming/burst-mode-streaming so along the lines of
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="..."
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="..." xmlns:ccfd="..." xmlns:hcfd="..." xmlns:ucf="..." xmlns:ucfd="..."
exclude-result-prefixes="ns0 xs">
<xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
<!-- start with this named template -->
<xsl:template name="main">
<MemberRecord xsi:schemaLocation="...">
<Patient>
<xsl:stream href='employees.xml'>
<xsl:apply-templates select="copy-of(ns0:ORM_O01/ns0:ORM_O01.PATIENT/ns0:PID)"/>
</xsl:stream>
</Patient>
</MemberRecord>
</xsl:template>
<xsl:template match="ns0:PID">
<ucfd:Name value="{...}"/>
<ucfd:FirstName value="{ns0:PID.5/ns0:XPN.2[not(translate(#xsi:nil, 'true ', '1') = '1'))]}"/>
<ucfd:LastName value="{ns0:PID.5/ns0:XPN.1/ns0:FN.1}"/>
<!-- compute the other elements and attributes here as above -->
</xsl:template>
</xsl:stylesheet>
That should show the approach, you will have to add code for the remaining elements like middle name and prefix and so on. I have also tried to simplify the compuation of the attribute value in some cases, I think the same can be done for the other cases but I think you should ask that in a different question where you provide details of the XML structure and the values you want to compute, all those nested for-eachs to generate a single value attribute seem a bit convoluted.
Also note that I have followed your posted code in creating a single Patient element, I would however expected that a ns0:ORM_O01.PATIENT element is mapped to a Patient so more along the lines of
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="..."
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="..." xmlns:ccfd="..." xmlns:hcfd="..." xmlns:ucf="..." xmlns:ucfd="..."
exclude-result-prefixes="ns0 xs">
<xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
<!-- start with this named template -->
<xsl:template name="main">
<MemberRecord xsi:schemaLocation="...">
<xsl:stream href='employees.xml'>
<xsl:apply-templates select="copy-of(ns0:ORM_O01/ns0:ORM_O01.PATIENT)"/>
</xsl:stream>
</Patient>
</MemberRecord>
</xsl:template>
<xsl:template match="ns0:ORM_O01.PATIENT">
<Patient>
<xsl:apply-templates/>
</Patient>
</xsl:template>
<xsl:template match="ns0:PID">
<ucfd:Name value="{...}"/>
<ucfd:FirstName value="{ns0:PID.5/ns0:XPN.2[not(translate(#xsi:nil, 'true ', '1') = '1'))]}"/>
<ucfd:LastName value="{ns0:PID.5/ns0:XPN.1/ns0:FN.1}"/>
<!-- compute the other elements and attributes here as above -->
</xsl:template>
</xsl:stylesheet>
I needs an XSLT function to create key-value strings sequence ( 'key1_val1', 'key2_val2', 'key3_val3' ) from plain strings sequence ( 'key1', 'val1', 'key2', 'val2', 'key3', 'val3' ).
I was stopped on the following code and have no ideas to continue:
<xsl:function name="bx:generate-pairs" as="xs:string*">
<xsl:param name="seq" as="xs:string*"/>
<xsl:sequence select="for $key in $seq return ..."/>
</xsl:function>
XSLT processor Saxon 9.3
You are looking for
for $i in (1 to count($seq))[. mod 2 = 1] return concat($seq[$i], '_', $seq[$i + 1])