I have the following XSLT Section Menu Code which working correctly to retreive items. But I'd like to replaced the items query by items name how ?
<!--<xsl:if test="contains($EnabledTemplates, concat('!', #template, '!')) ">-->
<xsl:for-each select="$root/item[contains($EnabledTemplates, concat('!', #template, '!'))]">
<xsl:sort select="#sortorder" data-type="number" />
<xsl:variable name="IsHaveChild" select="boolean(./item)" />
<xsl:variable name="IsSelected" select="boolean(./descendant-or-self::item[#id=$sc_currentitem/#id])" />
<xsl:variable name="IsShow" select="boolean(sc:fld($IsHideFieldName,.)!=1)" />
<xsl:variable name="IsCurrent" select="boolean(#id=$sc_currentitem/#id)" />
<sc:sec />
Do you want to filter items by name?
Try something like this:
[contains(#name, 'some text')]
For your querying you can choose between XPath and Sitecore query. The latter is a Sitecore implementation of XPath which is more readable and allows you to use the item names instead of XPath syntax.
Sitecore query however cannot be put directly in a select attribute in your XSL elements, it only works in the Sitecore XSL helper functions like sc:item (please also not the . in the sc:item function to specify the context item in which the query needs to be applied, . stands for current item).
<!-- using XPath -->
<xsl:value-of select="/item[#key='sitecore']/item[#key='content']" />
<!-- using Sitecore query -->
<xsl:value-of select="sc:item('/sitecore/content', .)" />
Related
I'm using xslt 1.0 to transform a Sharepoint 2013 Data View.
The data source consists of 3 joined lists:
ISOList
Threat_Catalogue (has a lookup (multiple) to ISOList)
Risks (has a lookup (single) to Threat_Catalogue)
I'm looping thru items in ISOList, and want to show all Risks that are relevant for this specific item. The logic being: First find Threats related to the specific item in ISOList, and then find Risks related to one of those Threats.
So I'm calling a template with the item ID (ISORef) from ISOList as a parameter - like so:
<xsl:template name="Risks">
<xsl:param name="ISORef" />
<!-- add extra info to string, so it only selects relevant items -->
<xsl:variable name="ISORefString" select="concat('&ID=',$ISORef,'&RootFolder')"/>
<!-- get relevant threats -->
<xsl:variable name="SelectedThreats" select="/dsQueryResponse/Threat_Catalogue/Rows/Row[contains(#ISO_x0020_Reference, $ISORefString)]"/>
<!-- Create variable, that contains all ID's in Threat_Catalogue that are relevant -->
<xsl:variable name="ListThreats"><xsl:for-each select="$SelectedThreats">=<xsl:value-of select="#ID"/>&</xsl:for-each></xsl:variable>
<!-- Variable - just to illustrate problem -->
<xsl:variable name="ListThreatsAlternative" select="$ListThreats" />
<!-- this is where I'm trying to use variable to get relevant risks, but fails -->
<!-- Old: Didn't Work, has been replaced -->
<!--
<xsl:variable name="SelectedRisks" select="/dsQueryResponse/Risks/Rows/Row[contains($ListThreats, substring-before(substring-after(#Threat, 'ID'), 'RootFolder'))]"/>
-->
<!-- New: Works as intended -->
<xsl:variable name="SelectedRisks" select="/dsQueryResponse/Risks/Rows/Row[contains($ListThreats, substring-before(substring-after(#Threat, 'ID'), 'RootFolder')) and $ListThreats != '' and #Threat != '']"/>
<!-- Example output: -->
Original: <xsl:value-of select="$ListThreats" /> <!-- contains: '=118&' --> <br/>
Alternative: <xsl:value-of select="$ListThreatsAlternative" /> <!-- empty -->
</xsl:template>
The problem is that variable ListThreats appears as an empty string when used as a criteria in the select for either SelectedRisks or ListThreatsAlternative.
*Edited:
The source XML is generated by Sharepoint. I don't know how to get the XML of the specific data source, but below I've added the XML from the Risks list. I've shortened down the XML source substantially, but hopefully it is sufficient.
Also - there are some significant differences in source XML and what Sharepoint presents in a list. Especially when it comes to the lookup-fields.
Example:
When Sharepoint presents the content:
https://xxx.xxx.xxx.com/sites/xxx_xxx/ISMS/_layouts/15/listform.aspx?PageType=4&ListId={4ab4bbff-588b-4c06-9685-c814cdefd59f}&ID=56&RootFolder=*', RefreshPage); return false;" href="https://xxx.xxx.xxx.com/sites/xxx_xxx/ISMS/_layouts/15/listform.aspx?PageType=4&ListId={4ab4bbff-588b-4c06-9685-c814cdefd59f}&ID=56&RootFolder=*">Hackers: 14. Password Cracking
When similar content is shown in source XML:
55;#Hackers: 13. Malware
This is the XML source (shortened):
<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="ows_ID" rs:name="ID" rs:number="1">
<s:datatype dt:type="i4" dt:maxLength="4"/>
</s:AttributeType>
<s:AttributeType name="ows_LinkTitle" rs:name="Risk Title" rs:number="2">
<s:datatype dt:type="string" dt:maxLength="512"/>
</s:AttributeType>
<s:AttributeType name="ows_Threat" rs:name="Threat" rs:number="15">
<s:datatype dt:type="variant" dt:lookup="true" dt:maxLength="8009"/>
</s:AttributeType>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row ows_ID="72" ows_LinkTitle="Test risk" ows_Threat="55;#Hackers: 13. Malware" />
</rs:data>
</xml>
Found the answer, stupid mistake in the select. Edited in OP.
I have created a number of functoids on the map to validate the source node 'AdoptedDate' for default values (Equals defaultvalues into an Logical OR through to a Value functoid with a new default value. Then an Logical Not for if neither of the Equals are not true to map the source node 'AdoptedDate' across to the destination schema (xslt enclosed).
What I would like to do is implement this for all date fields in the source schema, can this be done.
Current Generated XSLT (Adopted Only)
<xsl:for-each select="Form/SDetails">
<xsl:variable name="var:v17" select="userCSharp:LogicalEq(string(NameDetails/AdoptedDate/text()) , "1900-09-09")" />
<xsl:variable name="var:v18" select="string(NameDetails/AdoptedDate/text())" />
<xsl:variable name="var:v19" select="userCSharp:LogicalEq($var:v18 , "1800-09-09")" />
<xsl:variable name="var:v20" select="userCSharp:LogicalOr(string($var:v17) , string($var:v19))" />
<xsl:variable name="var:v22" select="userCSharp:LogicalNot(string($var:v20))" />
<xsl:if test="string($var:v20)='true'">
<xsl:variable name="var:v21" select=""1901-01-01"" />
<p:AdoptedDate>
<xsl:value-of select="$var:v21" />
</p:AdoptedDate>
</xsl:if>
<xsl:if test="string($var:v22)='true'">
<xsl:variable name="var:v23" select="NameDetails/AdoptedDate/text()" />
<p:AdoptedDate>
<xsl:value-of select="$var:v23" />
</p:AdoptedDate>
</xsl:if>
Your options are
Use the same set of functoids on each field (this is what I take it you are trying to avoid)
Create an external class implements the logic that you can then call from the Scripting functoid.
Create an in-line script to do the logic. You can then have subsequent scripting fuctoids containing the same function name and parameters and it will only have a single script in the XSLT that they all call.
In all situations you will have to have to have a functoid linked to the source and destination fields.
In Sitecore I have an item of template that contains a field with a link to another item. I want to apply template to an item which id is specified in this link.
Field contains link like this:
<link url="/sitecore/content/.." linktype="internal" id="{AATB8C7-BBA55A..}" />
I have a variable (var) that gets item id from this link. When I'm just writing this id in apply template it works fine, but when I'm writing a variable in apply template it doesn't work. What I'm doing wrong? Thanks in advance.
<xsl:for-each select="item[#template='mytempalte']">
<xsl:variable name="var">
<xsl:value-of select="sc:fld('Field',.,'id')"/> - //(this gets an id from link)
</xsl:variable>
<xsl:apply-templates mode="other" select="sc:item('$var',.)" /><br />
</xsl:for-each>
You don't need the single quotes aroudn the var in the apply-templates line:
<xsl:apply-templates mode="other" select="sc:item($var,.)" /><br />
This question is very similar to XSL store node-set in variable. The major difference is that if XPath does not find a node which matches the filter, I would like to return the first unfiltered result.
The code I have here works, but I feel like it is a hack and not good XSL style. In this case, each chapter node is identified by a string id. The variable showChapter is the string identifying a chapter. If no chapter is found with this id attribute, I want to return the first chapter.
Relevant code:
<xsl:param name="showChapter" />
<!-- if $showChapter does not match any chapter id attribute,
set validShowChapter to id of first chapter.
-->
<xsl:variable name="validShowChapter">
<xsl:choose>
<xsl:when test="/book/chapter[#id=string($showChapter)][position()=1]">
<xsl:value-of select="$showChapter" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="/book/chapter[position()=1]/#id" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- I want $chapter to be a valid node-set so I can use it in
XPath select statements in my templates
-->
<xsl:variable
name="chapter"
select="/book/chapter[#id=string($validShowChapter)][position()=1]"
>
Is this approach as poor of a hack as I think it is, and if so could you point me to a better solution? I am using XSLT 1.0 processed by PHP5's XSLTProcessor, but XSLT 2.0 solutions are welcome.
The following should work. A lot of the usage of position() and string() in your example were unneeded, btw:
<xsl:param name="showChapter" />
<xsl:variable name="foundChapter" select="/book/chapter[#id = $showChapter]" />
<!-- Will select either the first chapter in $foundChapter, or
the first chapter available if $foundChapter is empty -->
<xsl:variable name="chapter"
select="($foundChapter | /book/chapter[not($foundChapter)])[1]" />
How can I sort a list in XSLT in the same order as my datatype drop down list?
I've tried the following without any success:
<xsl:variable name="tarrifs" select="umbraco.library:GetPreValues(1601)//preValue" />
<xsl:sort select="tarrifs" order="descending" />
I have a list of options in my datatype "Tariff Category" and I want to order the list in my XSLT in the same order as my datatype.
Order of my datatype:
UE tariff criteria
UE pricing proposals
UE tariff schedules
UE other charges
UE tariff strategy reports
MG tariff schedules
MG tariff reports
MG ancillary and other charges
To start with, <xsl:sort... must appear inside either a <xsl:apply-templates... or <xsl:for-each... tag.
To sort with subjective logic, like you need, there's a couple of approaches you can take. The simplest is probably this:
XML
<root>
<item>dog</item>
<item>cat</item>
<item>horse</item>
<item>dragonfly</item>
</root>
XSL
<!-- this sheet vars -->
<xsl:variable name='sort_order' select='"dragonfly|horse|dog|cat"' />
<!-- root and static content -->
<xsl:template match="/">
<xsl:apply-templates select='root/item'>
<xsl:sort select='string-length(substring-before($sort_order, current()/text()))' data-type='number' />
</xsl:apply-templates>
</xsl:template>
<!-- iteration content - animal -->
<xsl:template match='item'>
<p><xsl:value-of select='.' /></p>
</xsl:template>
You can test it out at this XMLPlayground session.
The concept, as you can probably see, is to declare the desired sort order as a string, then iteratively sort our nodes based on the position of each node's text value within that sort string.
Are you looking for something like this:-
Assuming your xml is this way:-
XML:
<preValues>
<preValue id="19">Value 1</preValue>
<preValue id="20">Value 2</preValue>
<preValue id="21">Value 3</preValue>
</preValues>
XSLT:
If you want to sort by id in descending order then do this way
<xsl:for-each select="umbraco.library:GetPreValues(1601)//preValue">
<xsl:sort select="#id" order="descending" />
<!-- Do Your Stuff -->
</xsl:for-each>
Follow the same methodology to sort by multiple attribute values.