Re: [xsl] Transform selected attribute to element when element already has a value | XSLT 2.0

Subject: Re: [xsl] Transform selected attribute to element when element already has a value | XSLT 2.0
From: "Sam Spade anonymousjuly1@xxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 22 May 2021 18:51:01 -0000
 Thanks!B  I tried a similar approach before.

Input:
<requestConfirmation xmlns="http://example/confirmation";>
B B B  <trade>
B B B B B B B  <cal>
B B B B B B B B B B B  <c>PRECEDING</c>
B B B B B B B B B B B  <bcs id="businessCenters">
B B B B B B B B B B B B B B B  <bc>USNY</bc>
B B B B B B B B B B B B B B B  <bc>GBLO</bc>
B B B B B B B B B B B  </bcs>
B B B B B B B  </cal> B 
B B B B B B B  <amount>
B B B B B B B B B B B  <currency id="settlementCurrency"
currencyScheme="http://example/iso4";>USD</currency>
B B B B B B B B B B B  <referenceAmount>StandardISDA</referenceAmount>
B B B B B B B B B B B  <cashSettlement>true</cashSettlement>
B B B B B B B  </amount>
B B B  </trade>
</requestConfirmation>
As you can see,B  the unwanted attribute currencyScheme still persists. Is
there a way to remove the attribute which is not in the $keepAttr list?

Output:
<requestProduct xmlns="http://fc.fasset/product";>
B B  <trade>
B B B B B  <cal>
B B B B B B B B  <c>PRECEDING</c>
B B B B B B B B  <bcs>
B B B B B B B B B B B  <id>businessCenters</id>
B B B B B B B B B B B  <bc>USNY</bc>
B B B B B B B B B B B  <bc>GBLO</bc>
B B B B B B B B  </bcs>
B B B B B  </cal>
B B B B B  <amount>
B B B B B B B B  <currency>USD</currency>
B B B B B B B B 
<id>settlementCurrency</id>http://example/iso4<referenceAmount>StandardISDA</
referenceAmount>
B B B B B B B B  <cashSettlement>true</cashSettlement>
B B B B B  </amount>
B B  </trade>
</requestProduct>



    On Saturday, May 22, 2021, 1:12:39 a.m. MST, Martin Honnen
martin.honnen@xxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
Am 22.05.2021 um 02:02 schrieb Sam Spade anonymousjuly1@xxxxxxxx:



2.B B B B  As I point out in the post,

B 

https://stackoverflow.com/questions/67575484/what-attribute-node-cannot-follo
w-non-attribute-node-in-element-content-tells

B 

it is not only very difficult to search value if an element (<currency>)
contains both element (<id>) and text value (USD) but also returns false
result.

B 

B B B B B B B B B B B B B B  <amount>
 B B B B B B B B B B B B B B B B B  <currency>
 B B B B B B B B B B B B B B B B B B B B 
<id>settlementCurrency</id>USD</currency>
 B B B B B B B B B B B B B B B B B 
<referenceAmount>StandardISDA</referenceAmount>
 B B B B B B B B B B B B B B B B B  <cashSettlement>true</cashSettlement>
 B B B B B B B B B B B B B B  </amount>

B 

That USD really is the value of <currency>. In this case, it is legitimate and
sensible to transform id as sibling element of its original element <currency>
(its parent is still <amount>) to:

B 

<amount>
 B B B  <currency>USD</currency>
 B B B  <id>settlementCurrency</id>
 B B B  <referenceAmount>StandardISDA</referenceAmount>
 B B B  <cashSettlement>true</cashSettlement>
 </amount>

  The flattened XML is very searchable (an index on 'currency' is good enough)
and can be transformed to JSON.



I am not sure an XSLT program can easily capture your rules but for the given
sample, if you insert a check on elements whether they both have attributes
and non-whitespace text content and in that case transform any attributes to
sibling following the element, the result is as you wanted:




<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 B  version="3.0"
 B  xmlns:xs="http://www.w3.org/2001/XMLSchema";
 B  exclude-result-prefixes="#all">
 B 
 B  <xsl:param name="namespace"
as="xs:string">http://fc.fasset/product</xsl:param>

 B  <xsl:param name="root" as="xs:string">requestProduct</xsl:param>
 B  <xsl:param name="keepAttr" static="yes" as="xs:string*" select="'href',
'id'"/>
 B 
 B  <xsl:strip-space elements="*"/>
 B  <xsl:output indent="yes"/>
 B 
 B  <xsl:template match="/*">
 B B B B B  <xsl:element name="{$root}" namespace="{$namespace}">
 B B B B B B B B B  <xsl:apply-templates select="@* , node()"/>
 B B B B B  </xsl:element>
 B  </xsl:template>
 B 
 B  <xsl:template match="*">
 B B B B B  <xsl:element name="{local-name()}" namespace="{$namespace}">
 B B B B B B B B B  <xsl:apply-templates select="@* , node()"/>
 B B B B B  </xsl:element>
 B  </xsl:template>
 B 
 B  <xsl:template match="*[@* and text()[normalize-space()]]">
 B B B B B  <xsl:element name="{local-name()}" namespace="{$namespace}">
 B B B B B B B B B  <xsl:apply-templates/>
 B B B B B  </xsl:element>
 B B B B B  <xsl:apply-templates select="@*"/>
 B  </xsl:template>
 B 
 B  <xsl:template match="@*[local-name() = $keepAttr]">
 B B B B B  <xsl:element name="{local-name()}" namespace="{$namespace}">
 B B B B B B B  <xsl:value-of select="."/>
 B B B B B  </xsl:element>
 B  </xsl:template>

 </xsl:stylesheet>



 XSL-List info and archiveEasyUnsubscribe(by email)

Current Thread