XSLT Attribute match is not allowed on this element - xaml

I'm getting Attribute match is not allowed on this element errors on all these elements XAML except the root. I think I'm missing something about the syntax...
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates match="/Table"/>
<xsl:apply-templates match="/Paragraph"/>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table>
<xsl:apply-templates match="TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="TableRowGroup">
<xsl:apply-templates match="TableRow"/>
</xsl:template>
<xsl:template match="TableRow">
<tr>
<xsl:apply-templates match="TableCell"/>
</tr>
</xsl:template>
<xsl:template match="TableCell">
<td>
</td>
</xsl:template>
</xsl:stylesheet>

Use <xsl:apply-templates select="..."/> instead of <xsl:apply-templates match="..."/>.

Related

XLST 1.0 Split node

I want to split this node at <foo>:
<p>
<span>This is before foo.</span>
<foo>inside foo</foo>
<span>This is after foo.</span>
</p>
The result I want is
<p>
<span>This is before foo.</span>
</p>
<foo>inside foo</foo>
<p>
<span>This is after foo.</span>
</p>
But I'm getting
<p>
<span>This is before foo.</span>
<p>
<span>This is before foo.</span>
</p>
<foo>inside foo</foo>
<p>
<span>This is after foo.</span>
</p>
<span>This is after foo.</span>
</p>
And here's the style sheet I'm trying with:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="p/foo">
<xsl:element name="p">
<xsl:apply-templates select="preceding-sibling::node()"/>
</xsl:element>
<foo>
<xsl:apply-templates/>
</foo>
<xsl:element name="p">
<xsl:apply-templates select="following-sibling::node()"/>
</xsl:element>
</xsl:template>
</xsl:transform>
How can I get rid of that extra output?
Edit: Gave a more realistic example. See http://xsltransform.net/pNP88xQ/2
-- edited in response to your edited question --
This is not an easy task to accomplish in XSLT 1.0 (it's much easier to do in XSLT 2.0 using xsl:for-each-group).
One possible approach is a method known as sibling recursion:
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" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<!-- start sibling recursion -->
<xsl:apply-templates select="node()[1]"/>
</xsl:template>
<!-- first node in a group -->
<xsl:template match="p/node()[not(self::foo)]">
<p>
<xsl:call-template name="identity"/>
<!-- collect the following node in this group -->
<xsl:apply-templates select="following-sibling::node()[1][not(self::foo)]" mode="collect"/>
</p>
<!-- continue recursion with the following divider -->
<xsl:apply-templates select="following-sibling::foo[1]"/>
</xsl:template>
<!-- other nodes in a group -->
<xsl:template match="node()" mode="collect">
<xsl:call-template name="identity"/>
<!-- collect the following node in this group -->
<xsl:apply-templates select="following-sibling::node()[1][not(self::foo)]" mode="collect"/>
</xsl:template>
<xsl:template match="foo">
<xsl:call-template name="identity"/>
<!-- restart sibling recursion -->
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
</xsl:stylesheet>

xslt nested transformation : unable to transnform

I am learning XSLT and trying to transform below xml. But couldn't achieve the task
<sample id="7">
<land1 id="8">
<owner>TOMMY</owner>
<type>INDIVIDUAL</type>
<hint>TOM_INDIVIDUAL</hint>
<date>12.02.2014</date>
<text>land details</text>
<number>1</number>
<cost>WIDERRUFLICH</cost>
</land1>
</sample>
and trying to convert above into
<table name="sample">
<tablename="land1">
<rel name="owner" value="TOMMY"/>
<rel name="type" value="INDIVIDUAL"/>
<rel name="<hint" value="TOM_INDIVIDUAL"/>
<rel name="date" value="12.02.2014"/>
<rel name="details" value="land details"/>
<rel name="number" value="1"/>
<rel name="cost" value="25%"/>
</table>
</table>
I tried below to generate the same, but it's not working.
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="/">
<xsl:for-each select="*">
<xsl:if test="current().count(*)>0">
<xsl:element name="table">
<xsl:attribute name="name">
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:apply-templates select="/"
</xsl:element>
</xsl:if>
<xsl:if test="current().count(*)=0">
<xsl:element name="rel">
<xsl:attribute name="name">
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="current()"/>
</xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Can someone please let me know where I am doing wrong?
Can someone please let me know where I am doing wrong?
Well, for one thing, current().count(*)>0 is not a valid expression.
And you have <xsl:apply-templates select="/" without closing the tag. Which may be a good thing - because if it worked, it would have created an infinite loop.
I also don't understand the overall logic of your approach. Couldn't you do simply:
<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="*"/>
<xsl:template match="*[*]">
<table name="{name()}">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="*">
<rel name="{name()}" value="{.}"/>
</xsl:template>
</xsl:stylesheet>
Added:
every element with an attribute should also be a table. For example,
in the above xml, <land1 id="8"> has children and your logic works
fine. But my inout can also contain <land1 id="8"/>. Now even though
it doesn't have any child elements, still element name has to be
considered as Table
Then use:
<xsl:template match="*[#*]">
instead of:
<xsl:template match="*[*]">

Remove Duplicates from a list XSLT 1.0 based on element value

I need help with writing a function in xslt 1.0 that I can pass a list and it'll return the list with duplicates removed. It needs to be a template that I can easily clone or modify for other lists since there are several lists that I want to be able to run this.
Here is one example:
Input list:
<Diagnoses>
<Code>444.4</Code>
<Code>959.99</Code>
<Code>524</Code>
<Code>444.4</Code>
</Diagnoses>
Desired Output, after the duplicate code value 444.4 is removed:
<Diagnoses>
<Code>444.4</Code>
<Code>959.99</Code>
<Code>524</Code>
</Diagnoses>
Here is what I have so far, but it doesn't seem to be working:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://exslt.org/math"
xmlns:exsl="http://exslt.org/common"
xmlns:data="http://example.com/data" version="1.0"
extension-element-prefixes="math exsl"
exclude-result-prefixes="math exsl data">
<xsl:output omit-xml-declaration="yes" />
<xsl:variable name="DiagnosesList" select="Diagnoses"/>
<Diagnoses>
<xsl:call-template name="DedupeLists">
<xsl:with-param name="Input" select = "exsl:node-set($DiagnosesList)" />
</xsl:call-template>
</Diagnoses>
<xsl:template name="DedupeLists">
<xsl:param name = "Input" />
<xsl:for-each select="$Input/*">
<xsl:if test="Code[not(preceding::Code)]">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
#lingamurthy,
Just
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Code[. = preceding-sibling::Code]"/>
</xsl:stylesheet>
This is one way:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Code[not(. = preceding-sibling::Code)]">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Code"/>
</xsl:stylesheet>

Copy a node from parent to child

I would like to copy a parent node into the child but I'm unsure on how to proceed.
I apologize in advanced for the weird looking source file, I'm new to this forum and have no clue on how to properly paste an XML file.
My XML source file is like this:
<?xml version="1.0"?>
<IncidentLogUpload>
<Header>
<BatchID>2013</BatchID>
<SystemID>2013</SystemID>
<DateTime>12/20/2013 3:37 PM</DateTime>
</Header>
<Item>
<IncidentLogs>
<IncidentLog>
<IncidentSource>Source</IncidentSource>
<Property>Property</Property>
<Location>B1</Location>
<SubLocation/>
<DailyLogID>IN2013</DailyLogID>
<IncidentID>IN2013</IncidentID>
<Reference/>
<DateTimeOccured>12/19/2013 8:17 PM</DateTimeOccured>
<IncidentType>Surveillance</IncidentType>
<Specific>Observation</Specific>
<Category>POI</Category>
<IncidentDetails>0400</IncidentDetails>
<RelatedIncidentNo/>
<DateTimeReported>12/19/2013 8:17 PM</DateTimeReported>
<ParticipantSubjectProfiles>
<ParticipantSubjectProfile>
<FirstName>James</FirstName>
<MiddleName></MiddleName>
<LastName>Henderson</LastName>
<ParticipantType>Subject</ParticipantType>
<MembershipNumber></MembershipNumber>
<DriversLicense></DriversLicense>
<PassportNumber></PassportNumber>
<IncidentID>IN2013</IncidentID>
</ParticipantSubjectProfile>
</ParticipantSubjectProfiles>
<ParticipantPersonnelProfiles>
<ParticipantPersonnelProfile>
<BusinessUnit>Games</BusinessUnit>
<FirstName>Edison</FirstName>
<MiddleName>John</MiddleName>
<LastName>Costabile</LastName>
<CSELNumber/>
<StaffID>000408</StaffID>
<DriversLicense/>
<AffBUKey>GamesIN2013</AffBUKey>
<ParticipantType>Personnel</ParticipantType>
</ParticipantPersonnelProfile>
</ParticipantPersonnelProfiles>
</IncidentLog>
</IncidentLogs>
</Item>
<Footer>
<NumberOfRecords>5</NumberOfRecords>
</Footer>
</IncidentLogUpload>
I would like to copy the <Property> node to both <ParticipantSubjectProfile> and <ParticipantPersonnelProfile>. The end result should be like this:
<ParticipantSubjectProfiles>
<ParticipantSubjectProfile>
<FirstName>James</FirstName>
<MiddleName></MiddleName>
<LastName>Henderson</LastName>
<ParticipantType>Subject</ParticipantType>
<MembershipNumber></MembershipNumber>
<DriversLicense></DriversLicense>
<PassportNumber></PassportNumber>
<IncidentID>IN2013</IncidentID>
<Property>Property</Property>
</ParticipantSubjectProfile>
</ParticipantSubjectProfiles>
<ParticipantPersonnelProfiles>
<ParticipantPersonnelProfile>
<BusinessUnit>Games</BusinessUnit>
<FirstName>Edison</FirstName>
<MiddleName>John</MiddleName>
<LastName>Costabile</LastName>
<CSELNumber/>
<StaffID>000408</StaffID>
<DriversLicense/>
<AffBUKey>GamesIN2013</AffBUKey>
<ParticipantType>Personnel</ParticipantType>
<Property>Property</Property>
</ParticipantPersonnelProfile>
</ParticipantPersonnelProfiles>
Please help! Thank you!
Edited
<xsl:template match="/">
<ParticipantSubjectProfiles>
<xsl:for-each select="IncidentLogUpload/Item/IncidentLogs/IncidentLog/ParticipantSubjectProfiles">
<ParticipantSubjectProfile>
<FirstName>James</FirstName>
<MiddleName></MiddleName>
<LastName>Henderson</LastName>
<ParticipantType>Subject</ParticipantType>
<MembershipNumber></MembershipNumber>
<DriversLicense></DriversLicense>
<PassportNumber></PassportNumber>
<IncidentID>IN2013</IncidentID>
<Property> <xsl:value-of select="/IncidentLogUpload/Item/IncidentLogs/IncidentLog/Property"/></Property>
</ParticipantSubjectProfile>
</xsl:for-each>
</ParticipantSubjectProfiles>
</xsl:template>
</xsl:stylesheet>
Try this template out:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<ParticipantSubjectProfiles>
<xsl:for-each select="//ParticipantSubjectProfiles/ParticipantSubjectProfile">
<xsl:copy>
<xsl:apply-templates/>
<xsl:apply-templates select="../preceding-sibling::Property"></xsl:apply-templates>
</xsl:copy>
</xsl:for-each>
</ParticipantSubjectProfiles>
<ParticipantPersonnelProfiles>
<xsl:for-each select="//ParticipantPersonnelProfiles/ParticipantPersonnelProfile">
<xsl:copy>
<xsl:apply-templates/>
<xsl:apply-templates select="../preceding-sibling::Property"></xsl:apply-templates>
</xsl:copy>
</xsl:for-each>
</ParticipantPersonnelProfiles>
</xsl:template>
</xsl:stylesheet>

XAML XSLT attributes fail to match

When I try to transform this XAML document
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Arial" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="12" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0">
<Table CellSpacing="1" Margin="0,0,0,0"><Table.Columns><TableColumn Width="264" /></Table.Columns><TableRowGroup><TableRow><TableCell Padding="0,0,0,0">
<Paragraph FontFamily="Times New Roman" FontSize="10.666666666666666" Margin="0,0,0,0">
<Span FontWeight="Bold"><Run>some text</Run></Span><Run> </Run>
<Span Foreground="#FF00681C"><Run>some more text</Run></Span>
</Paragraph>
</TableCell></TableRow></TableRowGroup></Table>
</Section>
using this XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="/Table"/>
<xsl:apply-templates select="/Paragraph"/>
<xsl:apply-templates select="/Run"/>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table>
<xsl:apply-templates select="TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="TableRowGroup">
<xsl:apply-templates select="TableRow"/>
</xsl:template>
<xsl:template match="TableRow">
<tr>
<xsl:apply-templates select="TableCell"/>
</tr>
</xsl:template>
<xsl:template match="TableCell">
<td>
</td>
</xsl:template>
<xsl:template match="Paragraph">
<p>
<xsl:apply-templates select=""/>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="Run">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="Span">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
</xsl:stylesheet>
i get this incorrect result
<html>
<body>
some text some more text
</body>
I saw a few problems with your XSLT that would stop it working.
There is no namespace in the XSLT. There needs to be a namespace that
matches the one in the input XML, and you need to use this namespace
when matching elements.
Your first template matches "/", which matches the root node. I
assume you actually want to match the document element Section. The
apply-templates inside this are matching elements beginning with
"/", which makes them absolute paths, so they won't match anything.
I've taken a guess at what output XML you expect. The following XSLT stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
version="1.0"
exclude-result-prefixes="ns">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" method="html"/>
<xsl:template match="/ns:Section">
<html>
<body>
<xsl:apply-templates select="ns:Table"/>
</body>
</html>
</xsl:template>
<xsl:template match="ns:Table">
<table>
<xsl:apply-templates select="ns:TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="ns:TableRowGroup">
<xsl:apply-templates select="ns:TableRow"/>
</xsl:template>
<xsl:template match="ns:TableRow">
<tr>
<xsl:apply-templates select="ns:TableCell"/>
</tr>
</xsl:template>
<xsl:template match="ns:TableCell">
<td>
<xsl:apply-templates select="ns:Paragraph"/>
</td>
</xsl:template>
<xsl:template match="ns:Paragraph">
<p>
<xsl:apply-templates select="ns:Span"/>
</p>
</xsl:template>
<xsl:template match="ns:Run">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="ns:Span">
<span>
<xsl:apply-templates select="ns:Run"/>
</span>
</xsl:template>
</xsl:stylesheet>
produces the following output when applied to your example input XML:
<html>
<body>
<table>
<tr>
<td>
<p><span><span>some text</span></span><span><span>some more text</span></span></p>
</td>
</tr>
</table>
</body>
</html>
which may need a little formatting...