I would like to modify the content on the fly so I can later feed the modified version into my theme's content slot. The usecase is positioning the calendar portlet inside a collective.cover row/column/cell.
Here's what I tried:
<replace css:content="#content .row:nth-child(2) .cell:nth-child(2) .tile.tile-edge">
<!-- These work (meaning levels above current selection CAN be copied) -->
<xsl:copy-of select="." />
<xsl:copy-of select="../.." />
<xsl:copy-of select="/" />
<!-- However, neither of these do -->
<xsl:copy-of css:select=".portletCalendar:first-child" />
<xsl:copy-of select="//div[contains(concat(' ', normalize-space(#class), ' '), ' portletCalendar ')]" />
<xsl:copy-of select="//div[#id='portal-personaltools']" />
</replace>
It may be that the only problem you were having was relying on Diazo's facility for translating css selectors in XSL commands. It only works if the target is the currently selected node or a child of it. So, replace it with an XPath selector:
<!-- replace one part of content with another -->
<replace css:content="#content .row:nth-child(2) .cell:nth-child(2) .tile.tile-edge">
<xsl:copy-of select="//dl[#class='portlet portletCalendar']" />
<xsl:apply-templates mode="raw" />
</replace>
<!-- make sure it doesn't show up in two places -->
<drop content="//dl[#class='portlet portletCalendar']" />
Related
So far the only way to load my external document is to hardcode the path. I'd like to be able to use a relative path or variable.
I've created a Diazo rule which transforms content from an external page (called 'footer-columns') and places it in my themed pages.
Version A - This version works (note the hardcoded path):
<replace css:theme-children=".footer-menu-row">
<xsl:for-each
select="document('http://example.com/footer-columns')//*/dl[contains(#class,'portletStaticText')]/dd"
><div class="w-col w-col-3">
<xsl:copy-of select="." />
</div>
</xsl:for-each>
</replace>
Version B - This version does not work:
<replace css:theme-children=".footer-menu-row">
<xsl:for-each
select="document('{$portal_url}/footer-columns')//*/dl[contains(#class,'portletStaticText')]/dd"
><div class="w-col w-col-3">
<xsl:copy-of select="." />
</div>
</xsl:for-each>
</replace>
Version C - absolute path does not work (in fact it returns an error):
<replace css:theme-children=".footer-menu-row">
<xsl:for-each
select="document('/footer-columns')//*/dl[contains(#class,'portletStaticText')]/dd"
><div class="w-col w-col-3">
<xsl:copy-of select="." />
</div>
</xsl:for-each>
</replace>
Version D - relative path does not work (in fact it returns an error):
<replace css:theme-children=".footer-menu-row">
<xsl:for-each
select="document('footer-columns')//*/dl[contains(#class,'portletStaticText')]/dd"
><div class="w-col w-col-3">
<xsl:copy-of select="." />
</div>
</xsl:for-each>
</replace>
For version C and D I get the same error:
AttributeError: 'PersistentResourceDirectory' object has no attribute
'getPhysicalPath'
You need to provide a nodeset to the document() method. Diazo already sets a variable named diazo-base-document with the proper nodeset.
Try:
select="document('footer-columns', $diazo-base-document)//*/dl[contains(#class,'portletStaticText')"
Could you specify href="/footer-columns" on the replace tag?
I'm working on a DDR Treeview menu for DotNetNuke to display only the selected Root items and its child node to be expanded. Here is what I'm trying to achieve.
(Left vertical menu)
Any advice please?
This is the xslt code and is currently displaying all root items.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:param name="ControlID" />
<xsl:param name="Options" />
<xsl:template match="/*">
<xsl:apply-templates select="root" />
</xsl:template>
<xsl:template match="root">
<xsl:if test="node">
<ul class="treeview filetree" id="{$ControlID}">
<xsl:apply-templates select="node" />
</ul>
<script type="text/javascript">
jQuery(function($) {
$("#<xsl:value-of select="$ControlID" />").treeview(
<xsl:value-of select="$Options" disable-output-escaping="yes" />
);
});
</script>
</xsl:if>
</xsl:template>
<xsl:template match="node">
<li>
<xsl:if test="node and (#depth != 0 or #breadcrumb = 1)">
<xsl:attribute name="class">open</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="#enabled = 0">
<xsl:value-of select="#text" />
</xsl:when>
<xsl:otherwise>
<a href="{#url}">
<xsl:choose>
<xsl:when test="#selected=1">
<xsl:attribute name="class">selected breadcrumb</xsl:attribute>
</xsl:when>
<xsl:when test="#breadcrumb=1">
<xsl:attribute name="class">breadcrumb</xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:value-of select="#text" />
</a>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="node">
<ul style="list-item-style:none">
<xsl:apply-templates select="node" />
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
It would help if you supplied an example of the input code you would like to transform.
I assume its basically something like this:
<root>
<node enabled="1" depth="1" text="Service" selected="true" breadcrumb="0"/>
<node>
<node>
<node/>
</node>
</node>
<node>
<node/>
</node>
<node/>
</root>
You can skip the first template-match and those first if-element and directly match only what you're interested in. Without testing, something like this should do the trick:
<!-- ... -->
<!-- process only "root" elements that have at least one "node" element -->
<xsl:template match="/root[node]">
<ul class="treeview filetree" id="{$ControlID}">
<xsl:apply-templates select="node" />
</ul>
<!-- ... -->
</xsl:template>
<xsl:template match="node">
<!-- ... -->
</xsl:template>
Without the source XML it's really hard to work out what you're trying to do here, but I'd say the main reason you're getting all nodes is the the template to match the node element is recursive and does not hide the descendants. If you add display:none to the style attribute on the ul element at the end of the node template (or change list-item-style to display), you may get what you want.
If you're only getting root items, you'll want to change the NodeSelector defined for the menu. I believe that the shorthand value RootChildren will give you what you want.
I have a XHTML Template. I want to convert dynamically the xhtml file to xslt . Waht is the best way to do this?
Below written the XHTML content
<div>
{:header:}
<br />
{:date:}
<p>
{:mailingattn:} <br />
{:facilityname:} <br />
{:facilitystreet:} <br />
{:facilitystreet2:} <br />
{:facilitycity:}, {:facilitystate:} {:facilityzip:} <br />
{:facilitycountry:}
</p>
<p>
{:message:}
</p>
<p>
Sincerely,<br />
{:signature:}
</p>
{:footer:}
</div>
I don't know precisely the semantics of the macros used in your XHTML file, but the following transformation produces an XSLT stylesheet which is hopefully equivalent, and if not, should be easily tailored to your needs:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:element name="xsl:stylesheet">
<xsl:attribute name="version" select="'2.0'"/>
<xsl:element name="xsl:template">
<xsl:attribute name="match" select="'/*'"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:variable name="regex">\{:([a-zA-Z0-9]*):\}</xsl:variable>
<xsl:analyze-string select="." regex="{$regex}">
<xsl:matching-substring>
<xsl:element name="xsl:value-of">
<xsl:attribute name="select" select="regex-group(1)"/>
</xsl:element>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
Did you consider using XProc and <p:template> ?
http://www.w3.org/TR/xproc-template/#c.template
In the source XSD of the following map, InvTransTable and ToWarehouse elements are unbounded.
I want to map values only for the first iteration in each case. My problem is, the XSLT generated by the map contains two loops, as can be seen in the following:
<ns0:Record>
<xsl:for-each select="s1:InvTransTable">
<xsl:variable name="var:v4" select="position()" />
<xsl:for-each select="s1:ToWarehouse">
<xsl:variable name="var:v5" select="position()" />
<xsl:variable name="var:v6" select="userCSharp:LogicalEq(string($var:v5) , "1")" />
<xsl:variable name="var:v7" select="userCSharp:LogicalEq(string($var:v4) , "1")" />
<xsl:variable name="var:v8" select="userCSharp:LogicalAnd(string($var:v6) , string($var:v7))" />
<xsl:variable name="var:v12" select="userCSharp:StringUpperCase("B")" />
<xsl:variable name="var:v13" select="userCSharp:StringUpperCase("M")" />
<xsl:variable name="var:v14" select="userCSharp:StringUpperCase("4")" />
<ns0:Header>
<xsl:if test="string($var:v8)='true'">
<xsl:variable name="var:v9" select="s1:EXDRefCustAccount/text()" />
<ns0:AccountNo>
<xsl:value-of select="$var:v9" />
</ns0:AccountNo>
</xsl:if>
<xsl:if test="string($var:v7)='true'">
<xsl:variable name="var:v10" select="../s1:ShipDate/text()" />
<ns0:DateExpected>
<xsl:value-of select="$var:v10" />
</ns0:DateExpected>
</xsl:if>
This results in the created XML containing multiple header elements, which is not what I want!
I've tried to prevent this throug the use of Iteration (checking for a value of 1) and Conditional functoids but this hasn't worked. Can anyone please advise how I can achieve what is needed without resorting to a scripting functoid or replacing the map with XSLT?
If you know you only need to map the first instance of each, use the Index functoid with an index of 1, instead of the Iteration functoid.
I've basically got an XML input structure like this:
...
<box type="rectangle" class="someOriginalClass">
<background bgtype="solid" />
<animation order="3" />
... children
</box>
and would like to transform it to
<div class="someOriginalClass rectangle solid animated order3">
...children
</div>
Note that neither background nor animation need to be there, and this is a reduced example, meaning that there could be more properties like these, with more attributes.
As well, animation and background are reused elsewhere.
My XSLT code so far is:
<xsl:template match="box">
<div class="{#someOldClass} {#type}">
<xsl:apply-templates select="./*" />
</div>
</xsl:template>
<xsl:template match="background">
<xsl:attribute name="class">
<xsl:value-of select="#bgtype"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="animation">
<xsl:attribute name="class">
animated order<xsl:value-of select="#order"/>
</xsl:attribute>
</xsl:template>
The problem with this code is that each template overrides the class attribute completely, dismissing already contained classes.
To solve this, I've tried:
a) rewriting old classes => value-of only gets input XML class (someOldClass)
<xsl:template match="animation">
<xsl:attribute name="class">
<xsl:value-of select="../#class"/>
animated order<xsl:value-of select="#order"/>
</xsl:attribute>
</xsl:template>
b) instead passing changes between templates with params => only one time, one way
<xsl:template match="box">
<div class="{#someOldClass} {#type}">
<xsl:apply-templates select="./*">
<xsl:with-param name="class" select="concat(#someOldClass,' ',#type)"/>
</xml:apply-templates>
</div>
</xsl:template>
<xsl:template match="animation">
<xsl:param name="class"/>
<xsl:attribute name="class">
<xsl:value-of select="$class"/>
animated order<xsl:value-of select="#order"/>
</xsl:attribute>
</xsl:template>
You see, I'm lacking a solution that will work with any number of class updates, with minimal redundancy.
BTW, I'm an XSLT beginner, so maybe there's some predestined feature that I've simply not yet come across.
Any ideas?
I've used this before. I'm not sure what your XML looks like but this may help get you on the right path.
<xsl:template match="box">
<xsl:param name="boxType" />
<li>
<xsl:variable name="boxClass">
<xsl:value-of select="$boxType"/>
<xsl:if test="#class1 = 1"> class1</xsl:if>
<xsl:if test="#class2 = 1"> class2</xsl:if>
<xsl:if test="#class3 = 1"> class3</xsl:if>
<xsl:if test="#class4 = 1"> class4</xsl:if>
<xsl:if test="#last = 1"> lnLast</xsl:if>
</xsl:variable>
<xsl:attribute name="class">
<xsl:value-of select="$boxClass"/>
</xsl:attribute>
</li>
</xsl:template>