How to extra two date attributes to build a new text string - xslt-1.0

Here is a sample XML file:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk-Version2.xsl"?>
<MeetingWorkBook>
<Meeting BookmarkId="4" PageBreak="0" NumberClasses="1" SpecialEvent="0" CircuitVisit="0">
<Date ThisWeek="W20200831" NextWeek="W20200907">August 31–​September 6</Date>
</Meeting>
</MeetingWorkBook>
Here is a stripped down XSL file:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:param name="CSSFile1"></xsl:param>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
</head>
<body>
<div class="containerPage">
<xsl:for-each select="MeetingWorkBook/Meeting">
<div class="containerMeeting">
<!-- Put output here -->
</div>
</xsl:for-each>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I am interested in this element:
<Date ThisWeek="W20200831" NextWeek="W20200907">August 31–​September 6</Date>
Specifically, these attributes:
ThisWeek="W20200831"
NextWeek="W20200907"
The values are in the format of: WYYYYMMDD.
I need to display this text, for example:
Schedule date range - 31/08-6/09
The tasks I need to acheive:
Extract DD from ThisWeek (strip any leading 0).
Extract MM from ThisWeek (do not strip leading 0).
Extract DD from NextWeek and subtract 1 (strip any leading 0).
Extract MM from NextWeek (do not strip leading 0).
I realise that is might not be straightforward because we want to subtract 1 day which could theoretically be in the previous month. So if it is easier we could add 6 days to ThisWeek.
Can this be acheived with XSLT-1?
Thanks.

Related

Correct expression to compare variable in XSLT

Goal is to output "test" when info variable is set to "full". What am I doing wrong here?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<!-- Set Variable-->
<xsl:variable name="info" select="full" />
<!-- Test-->
<xsl:choose>
<xsl:when test="$info = 'full'">
<p>test</p>
</xsl:when>
<xsl:otherwise>
<p>test 2</p>
</xsl:otherwise>
</xsl:choose>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I'm looking for a simple solution to compare variable and do something based if it's true or not. Simple example yet it always outputs test2.
Your variable selects an element named full in the input XML - not a string containing the characters "full".
You test would return true if your input happened to be:
XML
<full>full</full>
Try instead:
<xsl:variable name="info" select='"full"' />

XSLT 1.0 Move last 4 characters in a string to a new node

I have the following XML:
<Documents>
<Form>
<FormCode>HP 1000 01 20</FormCode>
</Form>
<Form>
<FormCode>MS FULL 00 01 12 19</FormCode>
</Form>
</Documents>
The desired output:
<Documents>
<Form>
<FormCode>HP 1000</FormCode>
<FormDate>01 20</FormDate>
</Form>
<Form>
<FormCode>MS FULL 00 01</FormCode>
<FormDate>12 19</FormDate>
</Form>
</Documents>
I need to extract the last 4 characters of <FormCode> and place them in a new node <FormDate>. The length value of <FormCode> can vary for each form. Any ideas of how to accomplish this with XSLT 1.0 would be greatly appreciated. Thanks!
Try:
XSLt 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Form">
<xsl:variable name="len" select="string-length(FormCode)" />
<xsl:copy>
<FormCode>
<xsl:value-of select="substring(FormCode, 1, $len - 6)" />
</FormCode>
<FormDate>
<xsl:value-of select="substring(FormCode, $len - 4)" />
</FormDate>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Counting child notes in an document with multiple namespaces (XBRL)

I am trying (but not succeeding) to count the children in an XBRL document.
I want to know how many schemas, unit, contexts and facts grouped by namespace prefix are used.
Input:
<?xml version="1.0" encoding="utf-8"?>
<xbrl xml:lang="en" xmlns="http://www.xbrl.org/2003/instance"
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:find="http://www.eurofiling.info/xbrl/ext/filing-indicators"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<link:schemaRef xlink:type="simple" xlink:href="http://www.eba.europa.eu/eu/fr/xbrl/crr/fws/corep/its-2013-02/2014-03-31/mod/corep_le_con.xsd" />
<context id="I-2014-9-E">
<entity>
<identifier scheme="http://www.dnb.nl/id">123</identifier>
</entity>
<period>
<instant>2014-09-30</instant>
</period>
</context>
<unit id="u-EUR">
<measure>iso4217:EUR</measure>
</unit>
<unit id="u-pure">
<measure>pure</measure>
</unit>
<find:fIndicators>
<find:filingIndicator contextRef="I-2014-9-E">C_00.01</find:filingIndicator>
</find:fIndicators>
<find:fIndicators>
<find:filingIndicator contextRef="I-2014-9-E">C_26.00</find:filingIndicator>
</find:fIndicators>
<find:fIndicators>
<find:filingIndicator contextRef="I-2014-9-E">C_27.00</find:filingIndicator>
</find:fIndicators>
</xbrl>
Wanted output:
<?xml version="1.0" encoding="utf-8"?>
<XBRLfacts xmlns="http://www.xbrl.org/2003/instance" xmlns:link="http://www.xbrl.org/2003/linkbase">
<linkCount>1</linkCount>
<unitCount>2</unitCount>
<contextCount></contextCount>
<factCount>
<find>3</find>
</factCount>
</XBRLfacts>
XSLT tried:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.xbrl.org/2003/instance" xmlns:link="http://www.xbrl.org/2003/linkbase" >
<xsl:output method="xml" encoding="UTF-8" indent="yes" media-type="text/xml" />
<xsl:template match="/">
<XBRLfacts >
<linkCount>
<xsl:value-of select="//xbrl/link:schemaRef" />
</linkCount>
<unitCount>
<xsl:value-of select="//xbrl/unit" />
</unitCount>
<contextCount>
<xsl:value-of select="//xbrl/context" />
</contextCount>
<!-- something for the facts -->
</XBRLfacts>
</xsl:template>
</xsl:stylesheet>
Output gotten:
<?xml version="1.0" encoding="utf-8"?>
<XBRLfacts xmlns="http://www.xbrl.org/2003/instance" xmlns:link="http://www.xbrl.org/2003/linkbase">
<linkCount></linkCount>
<unitCount></unitCount>
<contextCount></contextCount>
</XBRLfacts>
Any help telling me what I am doing wrong is greatly appreciated.
Thanks.
Paul.
Your source elements are in namespaces. You must assign a prefix to each namespace and use it when addressing the elements in that namespace.
The other thing is that you're not actually counting anything.
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.xbrl.org/2003/instance"
xmlns:xbrl="http://www.xbrl.org/2003/instance"
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:find="http://www.eurofiling.info/xbrl/ext/filing-indicators"
exclude-result-prefixes="xbrl find">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/xbrl:xbrl">
<XBRLfacts>
<linkCount>
<xsl:value-of select="count(link:schemaRef)" />
</linkCount>
<unitCount>
<xsl:value-of select="count(xbrl:unit)" />
</unitCount>
<contextCount>
<xsl:value-of select="count(xbrl:context)" />
</contextCount>
<fIndicatorCount>
<xsl:value-of select="count(find:fIndicators)" />
</fIndicatorCount>
</XBRLfacts>
</xsl:template>
</xsl:stylesheet>
Result:
<?xml version="1.0" encoding="UTF-8"?>
<XBRLfacts xmlns="http://www.xbrl.org/2003/instance" xmlns:link="http://www.xbrl.org/2003/linkbase">
<linkCount>1</linkCount>
<unitCount>2</unitCount>
<contextCount>1</contextCount>
<fIndicatorCount>3</fIndicatorCount>
</XBRLfacts>

XSLT match a node where a child's child has an attribute with a value

I'm trying to parse out a FlowDocument that has a couple specific template match cases that I'm having trouble with.
So, for the Xaml document below (this was created by opening Word, creating the text, then copying into a WPF richtextbox and extracting the FlowDocument Xaml).
<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Span xml:lang="en-us">
<Span.TextDecorations>
<TextDecoration Location="Underline" />
</Span.TextDecorations>
List Item 2
</Span>
<Run>
<Run.TextDecorations>
<TextDecoration Location="Underline" />
</Run.TextDecorations>
List Item 3
</Run>
</FlowDocument>
Using the following Xslt, I'm trying to match the Span and Run tags that have a child node "TextDecoration" that has an attribute value "Location=Underline".
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="p:FlowDocument">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="p:Run/Run.TextDecorations/TextDecoration[#Location='Underline']">
<u>
<xsl:apply-templates />
</u>
</xsl:template>
</xsl:stylesheet>
I realize the above statement will not work, and if it actually did it would probably select the child node, not the parent node that I'm looking to get to.
The output I'm trying to get is the following:
<html xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<body>
<u>List Item 2</u>
<u>List Item 3</u>
</body>
</html>
I'm also having issues just matching "p:Run/Run.TextDecorations" element. Using Visual Studio, and stepping through the execution, it never finds the node I'm trying to find.
Any hints are welcome! Thanks!
There are a couple of ways you could match them. For example, you could specify the full path to descendant node you want to check for
<xsl:template
match="p:Run[p:Run.TextDecorations/p:TextDecoration/#Location='Underline']">
Or if you want to be less explicitly, and just check there was descendant matching at some level, you could do the following
<xsl:template
match="p:Span[descendant::p:TextDecoration/#Location='Underline']">
Do note the use of the namespace prefix on all elements in the XPath condition.
So, given the following XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation" exclude-result-prefixes="msxsl p">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p:Run[p:Run.TextDecorations/p:TextDecoration/#Location='Underline']">
<u>
<xsl:apply-templates/>
</u>
</xsl:template>
<xsl:template match="p:Span[descendant::p:TextDecoration/#Location='Underline']">
<u>
<xsl:apply-templates/>
</u>
</xsl:template>
<xsl:template match="p:FlowDocument">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
When applied to your sample XML, the following is output:
<html>
<body>
<u> List Item 2 </u>
<u> List Item 3 </u>
</body>
</html>

Displaying PDFs inline in Umbraco

Folks,
I've got badly stuck with something that I thought would be easy: I have a page and I want to display a PDF that's stored in my media collection.
I can link to a PDF using the standard toolbar but to embed a PDF, I have to turn to xslt and macro code.
This is what I have:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:Stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:template match="/">
<xsl:variable name="pdfFile" select="$currentPage/data [#alias='pdfFile']"/>
<xsl:if test="$pdfFile!= '' ">
<embed width="796" height="1032">
<xsl:attribute name="src">
<xsl:value-of select="umbraco.library:GetMedia(./data [#alias = 'pdfFile'], 'false')/data [#alias = 'umbracoFile']"/>
</xsl:attribute>
</embed>
</xsl:if>
</xsl:template></xsl:stylesheet>
But it's not working - I get nothing on the page. I've looked for solutions to this (perhaps my reference to GetMedia is wrong) but I can't find anything that'll help me.
Oh, my macro is using pdfFile as the parameter and is set as mediaCurrent.
I'm using Umbraco 4.7.1
Any pointers, help or advice would be great.
Thanks!
Actually, it's pretty easy.
Here it is documented for anyone using Umbraco 4.7.x and who needs to display pdf files:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:Stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<xsl:param name="pdf" select="/macro/pdfFile"/>
<xsl:template match="/">
<embed width="100%" height="500">
<xsl:attribute name="src">
<xsl:value-of select="$pdf/File/umbracoFile"/>
</xsl:attribute>
</embed>
</xsl:template>
</xsl:stylesheet>
For clarification, you will also need a macro (name unimportant) that uses this xslt. You will also have to add a parameter to the macro called pdfFile, click on the 'show' checkbox and then save it all.
The width and height of the embed can, of course, be set to whatever suits you.
Have fun.