xsl return the dynamic node value - xslt

hello:
do you guys know how to display the nodes' value which the nodes name are dynamic, for example, the nodes name is like x1, x2, x3... the number 1, 2 ,3 depends on the returns of the table.
i can get the node name using the loop, but only can get the name, even xsl:value-of select="$nodename", returns the nodename, not the value

As #Dimitre said, you haven't given us much specific information to work with, but in general you can use this to select elements whose names are determined at run time:
<xsl:value-of select="*[local-name() = $someDynamicValue]" />
You can also use name(), but local-name() ignores the namespace prefix, which usually makes things easier.
If you'd like more detailed help, please provide your sample input XML (especially the "returns of the table"), and the XSLT you've tried so far; and preferably, a sample of desired output XML.

Related

xquery/xslt for selecting a value based on a specific value

I am stuck on an xquery for below request. I want to select the address based on the type value.
i.e. if type is "StreetAddress" then pick freeFormat "Maguire"
<associatedAddress>
<address xmlns="http://services.oracle.com/v1.0/Common">
<type xmlns="http://services.oracle.com/v1.0/Common">StreetAddress</type>
<freeFormat xmlns="http://services.oracle.com/v1.0/Common">Maguire</freeFormat>
</address>
<address>
<type xmlns="http://services.oracle.com/v1.0/Common">CityAddress</type>
<freeFormat xmlns="http://services.oracle.com/v1.0/Common">SanFransisco</freeFormat>
</address>
</associatedAddress>
I tried in couple of ways:
if associatedAddress/address/type="StreetAddress"
then.., But this one gives me only the first address
I also tried to use a for loop and then use if case inside it but even that gave me just the first address
Please let me know any other options. Thanks
The XPath for fetching value Maguire using the value in <type> is
<xsl:value-of select="associatedAddress/address[type='StreetAddress']/freeFormat" />
You need to take care of the namespace associated with the different elements in your input XML when fetching the value. If the namespace is not properly handled in the XSL, the value will not be extracted.
Since you asked for xQuery given your input xml, this:
declare namespace common="http://services.oracle.com/v1.0/Common";
for $n in associatedAddress//common:type[. = "StreetAddress"]
return
$n/../common:freeFormat
produces the desired result
<freeFormat xmlns="http://services.oracle.com/v1.0/Common">Maguire</freeFormat>
The trick is that in your input xml associatedAddress is not in the same namespace as the other elements, so you need to adjust your query to take this into account.
You mention an if clause, but its is not clear what the desired output is from your question. You can use the below as a template to modify results.
declare namespace common="http://services.oracle.com/v1.0/Common";
for $n in associatedAddress//common:type
return
switch($n)
case "StreetAddress" return $n/../common:freeFormat
case "CityAddress" return "something else"
default
return ()

xslt dynamic xpath Saxon EE

I have following xml:
...
<peci:Address peci:isDeleted="1">
<peci:Usage_Type>WORK</peci:Usage_Type>
<peci:Address_Line_1>AMEC</peci:Address_Line_1>
<peci:Address_Line_2>2020 Winston Park Drive, Suite
700</peci:Address_Line_2>
<peci:City>Oakville</peci:City>
<peci:Postal_Code>L6H 6X7</peci:Postal_Code>
<peci:Country>CA</peci:Country>
<peci:Country_Region>ON</peci:Country_Region>
<peci:State_Province>Ontario</peci:State_Province>
</peci:Address>
<peci:Address peci:isAdded="1">
<peci:Usage_Type>WORK</peci:Usage_Type>
<peci:Address_Line_1>639 5th Avenue SW</peci:Address_Line_1>
<peci:Address_Line_2>Suite 1410</peci:Address_Line_2>
<peci:City>Calgary</peci:City>
<peci:Postal_Code>T2P 0M9</peci:Postal_Code>
<peci:Country>CA</peci:Country>
<peci:Country_Region>AB</peci:Country_Region>
<peci:State_Province>Alberta</peci:State_Province>
<peci:Address>
<peci:Usage_Type>HOME</peci:Usage_Type>
<peci:Address_Line_1>88 Bridge Cres.</peci:Address_Line_1>
<peci:City>Burlington</peci:City>
<peci:Postal_Code>L7L 0A3</peci:Postal_Code>
<peci:Country>CA</peci:Country>
<peci:Country_Region>ON</peci:Country_Region>
<peci:State_Province>Ontario</peci:State_Province>
</peci:Address>
<peci:Email/>
...
I iterate through the document and when find added node
peci:isAdded="1"
I check whether presiding node has the same element and has been deleted
peci:isDeleted="1"
if that is the case I would like to iterate through child elements and list all elements that are different (here everything but country)
I would like to use that for different nodes so I cannot use hard coded list of elements and when iterate through added element I dont know how to access the corresponding element in the proceeding sibling. It try sth like:
<xsl:when
test="../#peci:isAdded and ../preceding-sibling::*[../local-name()]/#peci:isDeleted">
<xsl:variable name="oldValueLocations" select="local-name()"/>
<xsl:value-of select="../preceding-sibling::*[../local-name()][#peci:isDeleted]/$oldValueLocations"/>
</xsl:when>
I would expect
<out:Row xtt:separator="," xtt:quotes="always">
<out:PayGroupCode>93JH</out:PayGroupCode>
<out:LegacyID>93JH000660265</out:LegacyID>
<out:WorkdayID>660265</out:WorkdayID>
<out:Name>SixWFNLastname SixWFNFirstname</out:Name>
<out:Status>Active</out:Status>
<out:Transaction>CHANGE</out:Transaction>
<out:Process_Type>DTA</out:Process_Type>
<out:Type>Address</out:Type>
<out:SubType>Country_Region</out:SubType>
<out:Effective_Date>2017-03-06</out:Effective_Date>
<out:Old_Value>ON</out:Old_Value>
<out:New_Value>AB</out:New_Value>
</out:Row>
but instead I get
<out:Row xtt:separator="," xtt:quotes="always">
<out:PayGroupCode>93JH</out:PayGroupCode>
<out:LegacyID>93JH000660265</out:LegacyID>
<out:WorkdayID>660265</out:WorkdayID>
<out:Name>SixWFNLastname SixWFNFirstname</out:Name>
<out:Status>Active</out:Status>
<out:Transaction>CHANGE</out:Transaction>
<out:Process_Type>DTA</out:Process_Type>
<out:Type>Address</out:Type>
<out:SubType>Country_Region</out:SubType>
<out:Effective_Date>2017-03-06</out:Effective_Date>
<out:Old_Value>WORK AMEC 2020 Winston Park Drive, Suite 700 Oakville L6H 6X7 CA ON
Ontario</out:Old_Value>
<out:New_Value>AB</out:New_Value>
</out:Row>
If you know about local-name() and predicate it seems selecting *[local-name() = $oldValueLocations] seems obvious to select elements of that name, probably with your other path prefixed (although I don't understand what the [../local-name()] is supposed to do).

XSLT select unknown nodes

I have some trouble with a special XML-document.
The XML has only 3 nodes like the below the example:
<solidName>
<unknownNodeName>
<everytimeTheSame>blablabla</everytimeTheSame>
<everytimeTheSame2>blablabla</everytimeTheSame2>
<unknownChildNodeName>
<everytimeTheSame>blablabla</everytimeTheSame>
<everytimeTheSame2>blablabla</everytimeTheSame2>
</unknownChildNodeName>
</unknownNodeName>
</solidName>
I need to select the unknownNodeName and the unknownChildNodeName to use the function
<xsl:value-of select="everytimeTheSame"/> and so on. I tried to use a for-each select function, but I found no way to get the unknow Name of the node.
Are there any possibilities for my problem? Is it possible to say <xsl:for-each select ="NodeNumberX"> or things like that <xsl:for-each select ="/*/*">
to use the function and so on
is not a good description of what you want to do.
Selecting "unknown nodes" (i.e. nodes whose name you do not know, but you do know their position in the document's tree) is trivial by using the * symbol in an XPath expression, possibly combined with a positional predicate.
For example:
/*/*/*[2]
will select the <everytimeTheSame2> element in your example.

How to use contains() with a set of strings in XSLT

I have the following XML snippet:
<figure customer="ABC DEF">
<image customer="ABC"/>
<image customer="XYZ"/>
</figure>
I'd like to check if the figure element's customer attribute contains the customer attributes of the image elements.
<xsl:if test="contains(#customer, image/#customer)">
...
</xsl:if>
I get an error saying:
a sequence of more than one item is not allowed as the second argument of contains
It's important to note that I cannot tell the values of the customer attributes in advance, thus using xsl:choose is not an option here.
Is it possible to solve this without using xsl:for-each?
In XSLT 2.0 you can use:
test="image/#customer/contains(../../#customer, .) = true()"
and you will get a true() result if any of them are true. Actually, that leads me to suggest:
test="some $cust in image/#customer satisfies contains(#customer, $cust)"
but that won't address the situation where the customer string is a subset of another customer string.
Therefore, perhaps this is best:
test="tokenize(#customer,'\s+') = image/#customer"
... as that will do a string-by-string comparison and give you true() if any of the tokenized values of the figure attribute is equal to one of the image attributes.

XSLT: attribute value used as numeric predicate

Given
<xsl:variable name="datePrecision" as="element()*">
<p>Year</p>
<p>Month</p>
<p>Day</p>
<p>Time</p>
<p>Timestamp</p>
</xsl:variable>
The expression
$datePrecision[5]
returns a nodeSet containing one text node with value "Timestamp", as expected.
Later in a template, with a context element having an attribute
#precision="5"
I try the following expressions but all return an empty string:
$datePrecision[#precision]
$datePrecision[number(#precision)]
$datePrecision[xs:decimal(#precision)]
However, the following sequence does what I want
<xsl:variable name="prec" select="number(#precision)"/>
... $datePrecision[$prec] ...
Using Oxygen/XML's debugger I've stepped to the point where the expression is about to be evaluated and display the following in the watch window:
Expression Value Nodes/Values Set
-------------------------- --------------- -----------------------
$datePrecision[5] Node Set(1) #text Timestamp
#precision Node Set(1) precision 5
$datePrecision[#precision]
number(#precision) 5
$datePrecision[number(#precision)]
$prec 5
$datePrecision[$prec] Node Set(1) #text Timestamp
Obviously I've missed something fundamental about how attribute nodes are atomized for use in a predicate, but can't find anything in the docs (Michael Kay's XSLT/XPATH 2.0, 4th ed) that would explain this difference.
Can someone explain why this is occurring, and point me to where, in either the XSLT 2.0 spec or Michael Kay's book, where this is described?
(the XSLT processor is Saxon-PE 9.2.0.3)
Obviously I've missed something
fundamental
Yes. The XPath expression:
$datePrecision[#precision]
means: all elements in $datePrecision that have an attribute named precision.
But you want #precision to mean the attribute named precision of the currnet node that is matched by the template.
XSLT provides the current() function exactly for this purpose. Use:
$datePrecision[current()/#precision]
UPDATE: As Martin Honnen hinted, the OP probably wants to get the 5th element out of $datePrecision -- something not immediately visible from the description of the problem. In this case, it may be necessary to use:
$datePrecision[position() = current()/#precision]