我有以下示例 XML:
<Example>
<SiteCode null="no">1ExampleSite</SiteCode>
<SiteName null="yes"/>
<CustomerPIN null="no">1234567</CustomerPIN>
<CustomerLastName null="no">Test </CustomerLastName>
<CustomerFirstName null="no">Example</CustomerFirstName>
<CustomerMiddleName null="yes"/>
<CustomerDOB null="no">2000-01-01 00:00:00.000</CustomerDOB>
<CustomerAddressLine1 null="no">1234 Easy ST</CustomerAddressLine1>
<CustomerAddressLine2 null="yes"/>
<CustomerCity null="no">Hartford</CustomerCity>
<CustomerState null="no">CT</CustomerState>
<CustomerZipCode null="no">123456</CustomerZipCode>
<CustomerGender null="no">F</CustomerGender>
<CustomerRaceCode null="no">White</CustomerRaceCode>
<CustomerRaceName null="yes"/>
</Example>
我想要做的是輸出 XML,以便地址節點在 HomeAddress/Address 下共享,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<Information>
<PIN>1234567</PIN>
<LastName>Test </LastName>
<FirstName>Example</FirstName>
<MiddleName/>
<DateOfBirth><DateNode>2000-01-01 00:00:00.000</DateNode></DateOfBirth>
<HomeAddress>
<Address>
<AddressLine1>1234 Easy ST</AddressLine1>
<AddressLine2/>
<City>Hartford</City>
<State>CT</State>
<ZipCode>123456</ZipCode>
</Address>
</HomeAddress>
<Gender><Code>F</Code></Gender>
<RaceCode>White</RaceCode>
<RaceName/>
</Information>
這是我當前的 XSLT 代碼:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:template match="/Example">
<Information>
<xsl:for-each select="*">
<xsl:apply-templates select=".[starts-with(local-name(), 'CustomerGender')]"/>
<xsl:apply-templates select=".[starts-with(local-name(), 'CustomerDOB')]"/>
<xsl:apply-templates select=".[starts-with(local-name(), 'CustomerAddress')
or starts-with(local-name(), 'CustomerCity')
or starts-with(local-name(), 'CustomerState')
or starts-with(local-name(), 'CustomerZipCode')][1]"/>
<xsl:apply-templates select=".[starts-with(local-name(), 'Customer')
and not(contains(local-name(), 'Gender'))
and not(contains(local-name(), 'Address'))
and not(contains(local-name(), 'City'))
and not(contains(local-name(), 'State'))
and not(contains(local-name(), 'ZipCode'))
and not(contains(local-name(), 'DOB'))]"/>
</xsl:for-each>
</Information>
</xsl:template>
<xsl:template match=".[starts-with(local-name(), 'Customer')]">
<xsl:element name="{replace(local-name(), 'Customer', '')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match=".[starts-with(local-name(), 'CustomerGender')]">
<xsl:element name="{replace(local-name(), 'Customer', '')}">
<Code>
<xsl:apply-templates/>
</Code>
</xsl:element>
</xsl:template>
<xsl:template match=".[starts-with(local-name(), 'CustomerDOB')]">
<DateOfBirth>
<DateNode>
<xsl:apply-templates/>
</DateNode>
</DateOfBirth>
</xsl:template>
<xsl:template match=".[starts-with(local-name(), 'CustomerAddress')
or starts-with(local-name(), 'CustomerCity')
or starts-with(local-name(), 'CustomerState')
or starts-with(local-name(), 'CustomerZipCode')]">
<HomeAddress>
<Address>
<xsl:for-each select=".">
<xsl:element name="{replace(local-name(), 'Customer', '')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</Address>
</HomeAddress>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
然而 - 這是我目前的輸出:
<?xml version="1.0" encoding="UTF-8"?>
<Information>
<PIN>1234567</PIN>
<LastName>Test </LastName>
<FirstName>Example</FirstName>
<MiddleName/>
<DateOfBirth><DateNode>2000-01-01 00:00:00.000</DateNode></DateOfBirth>
<Gender><Code>F</Code></Gender>
<RaceCode>White</RaceCode>
<RaceName/>
<HomeAddress><Address><AddressLine1>1234 Easy ST</AddressLine1></Address></HomeAddress><HomeAddress><Address><AddressLine2/></Address></HomeAddress>
<HomeAddress><Address><City>Hartford</City></Address></HomeAddress>
<HomeAddress><Address><State>CT</State></Address></HomeAddress>
<HomeAddress><Address><ZipCode>123456</ZipCode></Address></HomeAddress>
</Information>
如何更改此 XSL 邏輯以便獲得所需的輸出(共享的“地址”節點)而不是當前的(多個“地址”節點)?
對此我將不勝感激,我可能忽略了前面的示例,但我嘗試搜索并找不到任何特定于此場景的內容。
編輯:我知道可以在我擁有的“for-each”之外提取“地址”資訊,如下所示:
<xsl:for-each select="*">
<xsl:apply-templates select=".[starts-with(local-name(), 'CustomerGender')]"/>
<xsl:apply-templates select=".[starts-with(local-name(), 'CustomerDOB')]"/>
<xsl:apply-templates select=".[starts-with(local-name(), 'Customer')
and not(contains(local-name(), 'Gender'))
and not(contains(local-name(), 'Address'))
and not(contains(local-name(), 'City'))
and not(contains(local-name(), 'State'))
and not(contains(local-name(), 'ZipCode'))
and not(contains(local-name(), 'DOB'))]"/>
</xsl:for-each>
<HomeAddress>
<Address>
<xsl:apply-templates select="*[starts-with(local-name(), 'CustomerAddress')
or starts-with(local-name(), 'CustomerCity')
or starts-with(local-name(), 'CustomerState')
or starts-with(local-name(), 'CustomerZipCode')]"/>
</Address>
</HomeAddress>
但是,我還想保留資料的順序。如果客戶地址資訊位于資料中間,我希望它在輸出中顯示為這樣。
uj5u.com熱心網友回復:
您是否有理由不能簡單地做:
<xsl:stylesheet version="2.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="/Example">
<xsl:variable name="addr" select="CustomerAddressLine1 | CustomerAddressLine2 | CustomerCity | CustomerState | CustomerZipCode" />
<Information>
<xsl:copy-of select="* except $addr"/>
<HomeAddress>
<Address>
<xsl:copy-of select="$addr"/>
</Address>
</HomeAddress>
</Information>
</xsl:template>
</xsl:stylesheet>
添加:
假設地址欄位總是在一個連續的塊中,預期的輸出可以使用:
<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="/Example">
<xsl:variable name="addr" select="CustomerAddressLine1 | CustomerAddressLine2 | CustomerCity | CustomerState | CustomerZipCode" />
<Information>
<xsl:apply-templates select="$addr[1]/preceding-sibling::*[starts-with(name(), 'Customer')]"/>
<HomeAddress>
<Address>
<xsl:apply-templates select="$addr" />
</Address>
</HomeAddress>
<xsl:apply-templates select="$addr[last()]/following-sibling::*[starts-with(name(), 'Customer')]"/>
</Information>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{substring-after(name(), 'Customer')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="CustomerGender">
<Gender>
<Code>
<xsl:apply-templates/>
</Code>
</Gender>
</xsl:template>
<xsl:template match="CustomerDOB">
<DateOfBirth>
<DateNode>
<xsl:apply-templates/>
</DateNode>
</DateOfBirth>
</xsl:template>
</xsl:stylesheet>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/460766.html
