[英]how to convert nested xml elements to elements with attributes
我有这个源 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>
我希望它使用第 2 版样式表来转换成这种格式
<?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>
我目前有这个样式表,但由于某种原因,LocationDetails 元素被格式化为单个块属性,而不是它自己的名为 LocationDetails 的元素,它有自己的一组属性。 我试图遵循适用于这些元素的先前元素的格式设置,但我碰壁了。 与往常一样,任何帮助都感激不尽。
<?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>
</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>
	</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>
	</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>
	</xsl:text>
<a:Order>
<xsl:apply-templates select="*" />
<xsl:text>
	</xsl:text>
</a:Order>
</xsl:template>
<xsl:template match="OrderHeader">
<xsl:text>
		</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>
			</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>
这是不正确的输出,OrderHeader 元素中缺少的 orderdate/ordertime 到 orderdate 的转换可以在任何答案中被忽略,它的 locationdetails 就是问题所在。
<?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
优先考虑 LocationDetails 模板
<xsl:template match="LocationDetails" priority="2">
<xsl:text>
			</xsl:text>
<a:LocationDetails>
<xsl:apply-templates select="ANACode"/>
</a:LocationDetails>
</xsl:template>
选项 2:
更改此模板
<xsl:template match="OrderHeader/*">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
对此:
<xsl:template match="OrderHeader/*[not(self::LocationDetails)]">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
不是真正的答案,只是关于您的方法的一般说明。 AFAICT,只需使用两个通用模板即可完成大部分所需的转换:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://127.0.0.1:8080">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[*]">
<xsl:element name="a:{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<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">
<a:StartOfTransmission SenderId="SENDERSID"
ReceiverId="RECEIVERSID"
TRANSDATE="13-09-2010"
TRANSTIME="12:00:00"
SenderReference="1234"
ReceiverReference=""
ApplicationReference="ORDHDR"/>
<a:FileDetails GenerationNumber="12344"
VersionNumber="0001"
FileCreationDate="25-04-2008"/>
<a:Order>
<a:OrderHeader OrderDate="13-09-2010"
OrderTime="16:00:00"
OrderReference="Order Ref1"
RetailerId="132">
<a:LocationDetails ANACode="5013546167507" CustomerLocationCode="16750"/>
</a:OrderHeader>
</a:Order>
</a:Document>
现在您只需要添加一些更具体的模板来处理异常 - 例如:
<xsl:template match="TRANSDATE">
<xsl:attribute name="transdatetime" select="concat(replace(., '(.{2})-(.{2})-(.{4})', '$3-$2-$1T'), ../TRANSTIME)"/>
</xsl:template>
<xsl:template match="TRANSTIME"/>
此外,我看不出指定indent="no"
然后使用xsl:text
添加自己的缩进的意义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.