遍历多个 XPath 结果 - 仅创建一个节点

基兰·奥贾坎加斯

我有以下示例 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>

但是,我还想保留数据的顺序。如果客户地址信息在数据中间,我希望它在输出中显示为这样。

迈克尔.hor257k

您是否有理由不能简单地做:

<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>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如果多个存在,则xpath仅获得一个节点

从另一个 XPath 结果获取 XPath 结果

获取多个结果xpath div文本和下一个div文本

XPath从多个随机选择一个节点

C#Selenium遍历XPath结果

Xidel:如何从一个节点处理多个结果?

遍历属性并使用结果创建一个 Expression<Func<>>

Gorm仅返回一个而不是多个结果

用循环遍历一个线程并处理多个结果

如何仅返回XPath中的第一个匹配结果?

LXML XPath表达式仅返回第一个子节点,而浏览器确认多个子节点

串联单个XPath查询的多个结果

一个文件中的多个跑步者仅产生第一个的结果

XPath 结果返回一个数组

UISearchController仅返回第一个结果,但Core Data有多个结果

一个领域有多个结果

xpath 作为函数和 xpath 在表创建时的不同结果

作为一个结果返回多个“ WITH CTE”查询的结果

在多个结果的页面上搜集一个结果的信息

PHP,遍历多个数组-某些数组只有1个结果

分析多个输入文件,仅输出一个包含一个最终结果的文件

启动多个线程,仅等待一个线程完成即可获得结果

如何仅获取第一个结果mysql php-foreach中的多个查询

Mysql子查询仅返回一个结果,即使列表中有多个ID

Powershell:多个 Select-Object 语句仅返回第一个出现的结果

如何创建一个列表并创建作为多个已解决承诺的结果填充列表的变量?

为什么当我有多个结果时,此powershell代码仅返回一个结果?

XPath谓词仅使用节点集中的第一个节点进行匹配

通过仅知道另一个节点的子节点的 xPath 获取值 - selenium