[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 341
  • Last Modified:

XSL transform to select all non-blank items and also exclude specific nodes

I need a comma separated list excluding the EffectiveDate node and with no trailing comma.
XML Snippet
 
<AddressList>
				<AddressList>
					<Address>
						<__Address>
							<AddressType>CONTACT</AddressType>
 
XSL snippet
 
<xsl:for-each select="*[.!='']">
			<xsl:choose>
				<xsl:when test="contains(local-name(), 'EffectiveDate')">
					<!-- do nothing-->
				</xsl:when>
				<xsl:when test="contains(local-name(),'SameAsContactAddrFlag')">
					<!-- do nothing-->
				</xsl:when>
				<xsl:when test="contains(local-name(),'AddressType')">
					<!-- do nothing-->
				</xsl:when>
				<xsl:otherwise>
					<xsl:if test="string()">
						<xsl:value-of select="."/>
						<xsl:if test="position() != last()">
							<xsl:text>, </xsl:text>
						</xsl:if>
					</xsl:if>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
							<SameAsContactAddrFlag/>
							<BldgName/>
							<SubBldgName/>
							<BldgNumber>1</BldgNumber>
							<Street1>Grange Close North</Street1>
							<Street2/>
							<Locality1>Henleaze</Locality1>
							<Locality2/>
							<Town>Bristol</Town>
							<County/>
							<PostCode>BS97BY</PostCode>
							<OrgName/>
							<DeptName/>
							<PoBox/>
							<EffectiveDate>2006-10-26 11:45:50</EffectiveDate>
						</__Address>
</__Address>
					</Address>
</AddressList>
			</AddressList>

Open in new window

0
PugwashXP
Asked:
PugwashXP
  • 3
  • 3
1 Solution
 
zc2Commented:
The template below forms a comma separated list of not empty elements, it skips the EffectiveDate element and does not put the trailing comma:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="__Address">
	<xsl:for-each select="*">
		<xsl:if test="name()!='EffectiveDate' and string-length(.)">
			<xsl:if test="position() != 1"><xsl:text>, </xsl:text></xsl:if>
			<xsl:value-of select="."/>
  		</xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Open in new window

0
 
PugwashXPAuthor Commented:
Many thanks for that which does exactly what's asked.

I'm afraid I omitted oine of the requirements which is also to skip the nodes'SameAsContactAddrFlag' and 'AddressType'.
0
 
zc2Commented:
just add

name()!='SameAsContactAddrFlag' and name()!='AddressType' and

into the test attribute
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
PugwashXPAuthor Commented:
Thanks again - almost there. Problem now is that there is a leading comma. See Snippets below.

Cheers

XSL
 
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="__Address">
		<xsl:for-each select="*">
			<xsl:if test="name()!='EffectiveDate' and name()!='SameAsContactAddrFlag' and name()!='AddressType' and 
 string-length(.)">
				<xsl:if test="position() != 1">
					<xsl:text>, </xsl:text>
				</xsl:if>
				<xsl:value-of select="position()"/><xsl:text>, </xsl:text>
				<xsl:value-of select="."/>
			</xsl:if>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>
 
XML
 
<?xml version="1.0" encoding="UTF-8"?>
<__Address>
	<AddressType>CONTACT</AddressType>
	<BldgName/>
	<SubBldgName/>
	<BldgNumber>47</BldgNumber>
	<Street1>RRRRRR</Street1>
	<Street2>ssssss</Street2>
	<Locality1/>
	<Locality2/>
	<Town>PEACEHAVEN</Town>
	<County/>
	<PostCode>BN10 7PE</PostCode>
	<PoBox/>
</__Address>
 
OUTPUT
 
<?xml version="1.0" encoding="UTF-8"?>, 4, 47, 5, RRRRRR, 6, ssssss, 9, PEACEHAVEN, 11, BN10 7PE

Open in new window

0
 
zc2Commented:
I created a string variable, it contains all elements names you don't want to be in output.
Then I use text search function contain() to find out is the current element forbidden.
I also use the same condition to find any preceding sibling in order to decide toplace a comma or not to do so.
Also I removed the xsl:if and moved the condition to the xsl:for-each. I gues the position() output you need only for debugging purposes and it will be fine this way.

Hope this solution will be suitable
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text" encoding="iso-8859-1"/>
	<xsl:template match="__Address">
		<xsl:variable name="forbidden" select="'(EffectiveDate)(SameAsContactAddrFlag)(AddressType)'"/>
		<xsl:for-each select="*[text() and not(contains($forbidden,concat('(',name(),')')))]">
			<xsl:if test="preceding-sibling::*[text() and not(contains($forbidden,concat('(',name(),')')))]">
				<xsl:text>,</xsl:text>
			</xsl:if>
			<xsl:value-of select="position()"/>
			<xsl:text>,</xsl:text>
			<xsl:value-of select="."/>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

Open in new window

0
 
PugwashXPAuthor Commented:
Many thanks for all your time
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now