遍历多个 XPath 结果 - 仅创建一个节点
Iterate Through Multiple XPath Results - Create ONLY ONE NODE
我有下面的例子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>
但是,我还想保留数据的顺序。如果客户地址信息位于数据中间,我希望它在输出中显示为这样。
有什么理由不能简单的做:
<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>
我有下面的例子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>
但是,我还想保留数据的顺序。如果客户地址信息位于数据中间,我希望它在输出中显示为这样。
有什么理由不能简单的做:
<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>