You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT2.0转换嵌套XML为带属性元素:LocationDetails转换异常求助

解决XSLT转换中LocationDetails元素错误转为属性的问题

源XML

<?xml version="1.0" encoding="UTF-8" ?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <StartOfTransmission>
        <SenderId>SENDERSID</SenderId>
        <ReceiverId>RECEIVERSID</ReceiverId>
        <TRANSDATE>13-09-2010</TRANSDATE>
        <TRANSTIME>12:00:00</TRANSTIME>
        <SenderReference>1234</SenderReference>
        <ReceiverReference/>
        <ApplicationReference>ORDHDR</ApplicationReference>
    </StartOfTransmission>
    <FileDetails>
        <GenerationNumber>12344</GenerationNumber>
        <VersionNumber>0001</VersionNumber>
        <FileCreationDate>25-04-2008</FileCreationDate>
    </FileDetails>
    <Order>
        <OrderHeader>
            <OrderDate>13-09-2010</OrderDate>
            <OrderTime>16:00:00</OrderTime>
            <OrderReference>Order Ref1</OrderReference>
            <RetailerId>132</RetailerId>
            <LocationDetails>
                <ANACode>5013546167507</ANACode>
                <CustomerLocationCode>16750</CustomerLocationCode>
            </LocationDetails>
        </OrderHeader>
    </Order>
</Document>

目标转换格式

<?xml version="1.0" encoding="UTF-8"?>
<a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/tbattributesxml2.xsd"
          xmlns:a="http://127.0.0.1:8080">
    
    <a:StartOfTransmission SenderId="SENDERSID" ReceiverId="RECEIVERSID" transdatetime="2010-09-13T12:00:00.000" SenderReference="1234" ReceiverReference="" ApplicationReference="ORDHDR"/>
    <a:FileDetails GenerationNumber="12344" VersionNumber="0001" FileCreationDate="2008-04-25T00:00:00.000"/>
    <a:Order>
        <a:OrderHeader orderdate="2010-09-13T16:00:00.000" OrderReference="Order Ref1" RetailerId="132" DeliveryType="CARR" BackOrderFlag="N" OrderType="B" InternetOrderReference="Internet Ref">
            <a:LocationDetails ANACode="5013546167507" CustomerLocationCode="16750"/>
        </a:OrderHeader>
    </a:Order>
</a:Document>

当前使用的XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:saxon="http://saxon.sf.net/"
    xmlns:a="http://127.0.0.1:8080"
    exclude-result-prefixes="xs"
    version="2.0" >
    
    <xsl:output method="xml" indent="no" />
    <xsl:strip-space elements="*"/>
       
    <xsl:template match="Document" >
        <xsl:text>&#xA;</xsl:text>
        <a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd">
            <xsl:apply-templates/>
        </a:Document>
    </xsl:template>
    
    <xsl:template match="StartOfTransmission">
        <xsl:text>&#xA;&#x9;</xsl:text>
        <a:StartOfTransmission transdatetime="{replace(TRANSDATE, '(.{2})-(.{2})-(.{4})', '$3-$2-$1')}T{TRANSTIME}">
            <xsl:apply-templates select="* except(TRANSDATE, TRANSTIME)"/>
        </a:StartOfTransmission>
    </xsl:template> 
    
    <xsl:template match="StartOfTransmission/*">
        <xsl:attribute name="{name()}" select="."/>
    </xsl:template>  
    
    <xsl:template match="FileDetails">
        <xsl:text>&#xA;&#x9;</xsl:text>
        <xsl:variable name="dte" as="xs:string">
            <xsl:value-of select="concat(substring(FileCreationDate, 7, 4), '-', substring(FileCreationDate, 4, 2), '-', substring(FileCreationDate, 1, 2))"/>
        </xsl:variable>
        <xsl:variable name="dateTime" select="concat($dte,'T','00:00:00.000')"/>
        <a:FileDetails FileCreationDate="{$dateTime}">
            <xsl:apply-templates select="* except(FileCreationDate)"/>
        </a:FileDetails>      
    </xsl:template>
    
    <xsl:template match="FileDetails/*">
        <xsl:attribute name="{name()}" select="."/>
    </xsl:template>  
    
    <xsl:template match="Order">
        <xsl:text>&#xA;&#x9;</xsl:text>
        <a:Order>
            <xsl:apply-templates select="*" />
            <xsl:text>&#xA;&#x9;</xsl:text>
        </a:Order>
    </xsl:template>
    

    <xsl:template match="OrderHeader">
        <xsl:text>&#xA;&#x9;&#x9;</xsl:text>       
        <a:OrderHeader >
            <xsl:apply-templates select="*"/>
        </a:OrderHeader>
    </xsl:template>
    
    <xsl:template match="OrderHeader/*">
        <xsl:attribute name="{name()}" select="."/>
        
    </xsl:template>  
    
    <xsl:template match="LocationDetails">
        <xsl:text>&#xA;&#x9;&#x9;&#x9;</xsl:text>
        <a:LocationDetails>
            <xsl:apply-templates select="ANACode"/>
        </a:LocationDetails> 
        
    </xsl:template>
    
    <xsl:template match="LocationDetails/*">
        <xsl:attribute name="{name()}" select="*"/>
    </xsl:template> 
    
</xsl:stylesheet>

错误输出

<?xml version="1.0" encoding="UTF-8"?>
<a:Document xmlns:a="http://127.0.0.1:8080" xmlns:saxon="http://saxon.sf.net/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd">
    <a:StartOfTransmission transdatetime="2010-09-13T12:00:00" SenderId="SENDERSID" ReceiverId="RECEIVERSID" SenderReference="1234" ReceiverReference="" ApplicationReference="ORDHDR"/>
    <a:FileDetails FileCreationDate="2008-04-25T00:00:00.000" GenerationNumber="12344" VersionNumber="0001"/>
    <a:Order>
        <a:OrderHeader OrderDate="13-09-2010" OrderTime="16:00:00" OrderReference="Order Ref1" RetailerId="132" LocationDetails="501354616750716750"/>
    </a:Order></a:Document>

问题分析与修复方案

问题原因

  1. OrderHeader/*模板会匹配OrderHeader下的所有子元素,包括LocationDetails,将其直接转换为OrderHeader的属性,覆盖了LocationDetails自身的模板逻辑
  2. LocationDetails模板仅处理了ANACode子元素,遗漏了CustomerLocationCode
  3. LocationDetails/*模板中属性值选取错误(select="*"会选取子元素而非当前元素的值)

修复后的XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:saxon="http://saxon.sf.net/"
    xmlns:a="http://127.0.0.1:8080"
    exclude-result-prefixes="xs"
    version="2.0" >
    
    <xsl:output method="xml" indent="no" />
    <xsl:strip-space elements="*"/>
       
    <xsl:template match="Document" >
        <xsl:text>&#xA;</xsl:text>
        <a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd">
            <xsl:apply-templates/>
        </a:Document>
    </xsl:template>
    
    <xsl:template match="StartOfTransmission">
        <xsl:text>&#xA;&#x9;</xsl:text>
        <a:StartOfTransmission transdatetime="{replace(TRANSDATE, '(.{2})-(.{2})-(.{4})', '$3-$2-$1')}T{TRANSTIME}">
            <xsl:apply-templates select="* except(TRANSDATE, TRANSTIME)"/>
        </a:StartOfTransmission>
    </xsl:template> 
    
    <xsl:template match="StartOfTransmission/*">
        <xsl:attribute name="{name()}" select="."/>
    </xsl:template>  
    
    <xsl:template match="FileDetails">
        <xsl:text>&#xA;&#x9;</xsl:text>
        <xsl:variable name="dte" as="xs:string">
            <xsl:value-of select="concat(substring(FileCreationDate, 7, 4), '-', substring(FileCreationDate, 4, 2), '-', substring(FileCreationDate, 1, 2))"/>
        </xsl:variable>
        <xsl:variable name="dateTime" select="concat($dte,'T','00:00:00.000')"/>
        <a:FileDetails FileCreationDate="{$dateTime}">
            <xsl:apply-templates select="* except(FileCreationDate)"/>
        </a:FileDetails>      
    </xsl:template>
    
    <xsl:template match="FileDetails/*">
        <xsl:attribute name="{name()}" select="."/>
    </xsl:template>  
    
    <xsl:template match="Order">
        <xsl:text>&#xA;&#x9;</xsl:text>
        <a:Order>
            <xsl:apply-templates select="*" />
            <xsl:text>&#xA;&#x9;</xsl:text>
        </a:Order>
    </xsl:template>
    

    <xsl:template match="OrderHeader">
        <xsl:text>&#xA;&#x9;&#x9;</xsl:text>       
        <a:OrderHeader >
            <!-- 应用模板时排除LocationDetails,让其使用自身模板 -->
            <xsl:apply-templates select="* except(LocationDetails)"/>
            <!-- 单独处理LocationDetails -->
            <xsl:apply-templates select="LocationDetails"/>
        </a:OrderHeader>
    </xsl:template>
    
    <!-- 修改匹配模式,排除LocationDetails,避免将其转为属性 -->
    <xsl:template match="OrderHeader/*[not(self::LocationDetails)]">
        <xsl:attribute name="{name()}" select="."/>
    </xsl:template>  
    
    <xsl:template match="LocationDetails">
        <xsl:text>&#xA;&#x9;&#x9;&#x9;</xsl:text>
        <a:LocationDetails>
            <!-- 处理所有子元素,包括ANACode和CustomerLocationCode -->
            <xsl:apply-templates select="*"/>
        </a:LocationDetails> 
    </xsl:template>
    
    <!-- 修正属性值选取逻辑,取当前元素的值 -->
    <xsl:template match="LocationDetails/*">
        <xsl:attribute name="{name()}" select="."/>
    </xsl:template> 
    
</xsl:stylesheet>

修复说明

  1. 修改OrderHeader模板:在apply-templates时排除LocationDetails,并单独调用其模板,确保LocationDetails作为独立元素生成
  2. 调整OrderHeader/*的匹配模式,添加[not(self::LocationDetails)],避免将LocationDetails转换为属性
  3. 更新LocationDetails模板的apply-templates范围为*,确保所有子元素都被处理
  4. 修正LocationDetails/*模板的属性值选取为select=".",正确获取当前元素的文本内容作为属性值

内容的提问来源于stack exchange,提问作者blm99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 09:24:25