XSLT - Select 两个节点之间的节点(基于数组)?
XSLT - Select Nodes (Based On Arrays) Between Two Nodes?
我现在有以下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>
<CustomerGender null="no">F</CustomerGender>
<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>
<CustomerRaceCode null="no">White</CustomerRaceCode>
<CustomerRaceName null="yes"/>
<CustomerReferral1Phone>8881234567</CustomerReferral1Phone>
<CustomerReferral2Phone>8881234567</CustomerReferral2Phone>
<CustomerReferral3Phone>8881234567</CustomerReferral3Phone>
<CustomerOrderNumber>48290275</CustomerOrderNumber>
<ShopDesignationNumber>4572</ShopDesignationNumber>
<CustomerFirstOrderDate>2020-11-13</CustomerFirstOrderDate>
</Example>
我还有以下 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">
<xsl:variable name="addr" select="CustomerAddressLine1 | CustomerAddressLine2 | CustomerCity | CustomerState | CustomerZipCode" />
<xsl:variable name = "referralContact1" select="*[starts-with(local-name(), 'CustomerReferral1')]"/>
<xsl:variable name = "referralContact2" select="*[starts-with(local-name(), 'CustomerReferral2')]"/>
<xsl:variable name = "referralContact3" select="*[starts-with(local-name(), 'CustomerReferral3')]"/>
<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')]"/>
<CustomerReferrals>
<xsl:apply-templates select="$referralContact1"/>
<xsl:apply-templates select="$referralContact2"/>
<xsl:apply-templates select="$referralContact3"/>
</CustomerReferrals>
</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:template match="*[starts-with(local-name(), 'CustomerReferral')]">
<xsl:element name="{replace(local-name(), 'CustomerReferral[\d]', '')}">
<xsl:apply-templates/>
</xsl:element>
</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>
<HomeAddress>
<Address>
<AddressLine1>1234 Easy ST</AddressLine1>
<AddressLine2/>
<City>Hartford</City>
<State>CT</State>
<ZipCode>123456</ZipCode>
</Address>
</HomeAddress>
<RaceCode>White</RaceCode>
<RaceName/>
<CustomerReferrals>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
</CustomerReferrals>
<OrderNumber>48290275</OrderNumber>
<ShopDesignationNumber>4572</ShopDesignationNumber>
<FirstOrderDate>2020-11-13</FirstOrderDate>
</Information>
这是我当前的输出:
<?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>
<HomeAddress>
<Address>
<AddressLine1>1234 Easy ST</AddressLine1>
<AddressLine2/>
<City>Hartford</City>
<State>CT</State>
<ZipCode>123456</ZipCode>
</Address>
</HomeAddress>
<RaceCode>White</RaceCode>
<RaceName/>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<OrderNumber>48290275</OrderNumber>
<FirstOrderDate>2020-11-13</FirstOrderDate>
<CustomerReferrals>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
</CustomerReferrals>
</Information>
有什么方法可以确保我在“ReferralPhone”转换调用之前只选择地址节点和“ReferralPhone”节点之间的节点,这样我就不会创建这些额外的phone 行数?如果可能的话,我还想保留放入新 XML 中的元素的顺序。
不确定这通常是正确的方法,但它可以满足您的需求。这个想法是找出关键元素的上下文索引,然后为它们之间的节点应用模板。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<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:variable name="lastAddrIndex" select="count(*[contains(local-name(),'ZipCode')][1]/preceding-sibling::*)+1"/>
<xsl:variable name="firstRefIndex" select="count(*[contains(local-name(),'Phone')][1]/preceding-sibling::*)"/>
<xsl:variable name="lastRefIndex" select="count(*[contains(local-name(),'Phone')][last()]/preceding-sibling::*)"/>
<!-- process everything before phones -->
<xsl:apply-templates select="*[(position() <= $firstRefIndex)
and (position() > $lastAddrIndex)]"/>
<CustomerReferrals>
<xsl:apply-templates select="node()[contains(local-name(),'Phone')]"></xsl:apply-templates>
</CustomerReferrals>
<!-- process everything after phones -->
<xsl:apply-templates select="*[position() > $lastRefIndex]"/>
</Information>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="contains(name(), 'Customer')">
<xsl:element name="{substring-after(name(), 'Customer')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</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:template match="*[starts-with(local-name(), 'CustomerReferral')]">
<xsl:element name="{replace(local-name(), 'CustomerReferral[\d]', '')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我现在有以下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>
<CustomerGender null="no">F</CustomerGender>
<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>
<CustomerRaceCode null="no">White</CustomerRaceCode>
<CustomerRaceName null="yes"/>
<CustomerReferral1Phone>8881234567</CustomerReferral1Phone>
<CustomerReferral2Phone>8881234567</CustomerReferral2Phone>
<CustomerReferral3Phone>8881234567</CustomerReferral3Phone>
<CustomerOrderNumber>48290275</CustomerOrderNumber>
<ShopDesignationNumber>4572</ShopDesignationNumber>
<CustomerFirstOrderDate>2020-11-13</CustomerFirstOrderDate>
</Example>
我还有以下 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">
<xsl:variable name="addr" select="CustomerAddressLine1 | CustomerAddressLine2 | CustomerCity | CustomerState | CustomerZipCode" />
<xsl:variable name = "referralContact1" select="*[starts-with(local-name(), 'CustomerReferral1')]"/>
<xsl:variable name = "referralContact2" select="*[starts-with(local-name(), 'CustomerReferral2')]"/>
<xsl:variable name = "referralContact3" select="*[starts-with(local-name(), 'CustomerReferral3')]"/>
<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')]"/>
<CustomerReferrals>
<xsl:apply-templates select="$referralContact1"/>
<xsl:apply-templates select="$referralContact2"/>
<xsl:apply-templates select="$referralContact3"/>
</CustomerReferrals>
</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:template match="*[starts-with(local-name(), 'CustomerReferral')]">
<xsl:element name="{replace(local-name(), 'CustomerReferral[\d]', '')}">
<xsl:apply-templates/>
</xsl:element>
</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>
<HomeAddress>
<Address>
<AddressLine1>1234 Easy ST</AddressLine1>
<AddressLine2/>
<City>Hartford</City>
<State>CT</State>
<ZipCode>123456</ZipCode>
</Address>
</HomeAddress>
<RaceCode>White</RaceCode>
<RaceName/>
<CustomerReferrals>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
</CustomerReferrals>
<OrderNumber>48290275</OrderNumber>
<ShopDesignationNumber>4572</ShopDesignationNumber>
<FirstOrderDate>2020-11-13</FirstOrderDate>
</Information>
这是我当前的输出:
<?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>
<HomeAddress>
<Address>
<AddressLine1>1234 Easy ST</AddressLine1>
<AddressLine2/>
<City>Hartford</City>
<State>CT</State>
<ZipCode>123456</ZipCode>
</Address>
</HomeAddress>
<RaceCode>White</RaceCode>
<RaceName/>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<OrderNumber>48290275</OrderNumber>
<FirstOrderDate>2020-11-13</FirstOrderDate>
<CustomerReferrals>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
<Phone>8881234567</Phone>
</CustomerReferrals>
</Information>
有什么方法可以确保我在“ReferralPhone”转换调用之前只选择地址节点和“ReferralPhone”节点之间的节点,这样我就不会创建这些额外的phone 行数?如果可能的话,我还想保留放入新 XML 中的元素的顺序。
不确定这通常是正确的方法,但它可以满足您的需求。这个想法是找出关键元素的上下文索引,然后为它们之间的节点应用模板。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<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:variable name="lastAddrIndex" select="count(*[contains(local-name(),'ZipCode')][1]/preceding-sibling::*)+1"/>
<xsl:variable name="firstRefIndex" select="count(*[contains(local-name(),'Phone')][1]/preceding-sibling::*)"/>
<xsl:variable name="lastRefIndex" select="count(*[contains(local-name(),'Phone')][last()]/preceding-sibling::*)"/>
<!-- process everything before phones -->
<xsl:apply-templates select="*[(position() <= $firstRefIndex)
and (position() > $lastAddrIndex)]"/>
<CustomerReferrals>
<xsl:apply-templates select="node()[contains(local-name(),'Phone')]"></xsl:apply-templates>
</CustomerReferrals>
<!-- process everything after phones -->
<xsl:apply-templates select="*[position() > $lastRefIndex]"/>
</Information>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="contains(name(), 'Customer')">
<xsl:element name="{substring-after(name(), 'Customer')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</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:template match="*[starts-with(local-name(), 'CustomerReferral')]">
<xsl:element name="{replace(local-name(), 'CustomerReferral[\d]', '')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>