导入前XSLT转换XML:Product节点属性与子节点映射问题
问题
我有一份待导入的产品XML数据,需要在导入前用XSLT模板转换。目前写了基础模板,但无法正确提取以下内容:
<Product>节点的属性(如id、name等)<Images>子节点中的图片(区分主图与副图)<TechnicalSpecification>中的技术参数
希望得到能实现目标转换结构的示例代码。
待导入XML示例
<Products> <Product id="ADEBLDADE0001" name="Black Decker BL4018 Battery" producer="BLD" categoryId="ADE-ADE" warranty="F012M" priceNet="43.95" vat="23" vat_type="zwykły" pkwiu="27.20.23.0" externalWarehouse="N" available="30" date="2017-03-13" onOrder="N" specialOffer="N" lastChange="2022-10-17" smallPallet="N" productIsLarge="N" reported="T" EAN="5035048560044" manufacturerPartNumber="BL4018-XJ" sizeWidth="80" sizeLength="130" sizeHeight="110" weight="690" sizeMeasurementUnit="mm" weightMeasurementUnit="g" dimensionalWeight="228" additionalAvailabilityInfo="" expiryDate="1900-01-01" ETA="" incomingStock="0" mainCategoryTree="House and Garden" categoryTree="Tools - accessories" subCategoryTree="Batteries"> <Images> <Image url="/Icecat/O2N59732L0C0C1V6o7K4N143m7O7K7A8.jpg" isMain="0" date="2023-01-19" copyright="0" /> <Image url="/Icecat/I4B7m9t9K000X1b6w7V471A3H7R737c8.jpg" isMain="0" date="2023-01-19" copyright="0" /> <Image url="/Icecat/O9P0t7g7k0k0E1s6H7O4u1R3H7c757V9.jpg" isMain="1" date="2023-01-19" copyright="0" /> <Image url="/Icecat/I1P2w3a2c0r0N116X7E4P1a3n7l7w7q9.jpg" isMain="0" date="2023-01-19" copyright="0" /> <Image url="/Icecat/T9X096A3D0D0T1d6A7h481i3B7P7A8L0.jpg" isMain="0" date="2023-01-19" copyright="0" /> <Image url="/Icecat/Q1D233T3K020Z10607c421L3N7Z7Q8n1.jpg" isMain="0" date="2023-01-19" copyright="0" /> <Image url="/Icecat/Z2X2z2e5s03031B6G7r4j1Z2W4C9B926.jpg" isMain="0" date="2023-01-19" copyright="0" /> </Images> <Multimedia/> <TechnicalSpecification> <Section name="Features"> <Attributes> <Attribute name="Product type"> <Values> <Value Name="Battery"/> </Values> </Attribute> <Attribute name="Battery technology"> <Values> <Value Name="Lithium-Ion (Li-Ion)"/> </Values> </Attribute> <Attribute name="Battery capacity"> <Values> <Value Name="2 Ah"/> </Values> </Attribute> <Attribute name="Battery voltage"> <Values> <Value Name="18 V"/> </Values> </Attribute> <Attribute name="Product colour"> <Values> <Value Name="Grey"/> <Value Name="Black"/> <Value Name="Orange"/> </Values> </Attribute> <Attribute name="Number of batteries included"> <Values> <Value Name="1 pc(s)"/> </Values> </Attribute> </Attributes> </Section> </TechnicalSpecification> </Product> </Products>
已编写的XSLT模板
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:g="http://base.google.com/ns/1.0"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="Products"> <xsl:for-each select="Product"> <xsl:element name="Product"> <xsl:element name="id"> <xsl:value-of select="id"/> </xsl:element> </xsl:element> </xsl:for-each> </xsl:template> </xsl:stylesheet>
期望转换后的XML结构
<Products> <product> <id>ADEBLDADE0001</id> <name>Black Decker BL4018 Battery</name> <producer>BLD</producer> <categoryId>ADE-ADE</categoryId> <warranty>F012M</warranty> <priceNet>43.95</priceNet> <vat>23</vat> <vat_type>zwykły</vat_type> <pkwiu>27.20.23.0</pkwiu> <externalWarehouse>N</externalWarehouse> <available>30</available> <date>2017-03-13</date> <onOrder>N</onOrder> <specialOffer>N</specialOffer> <lastChange>2022-10-17</lastChange> <smallPallet>N</smallPallet> <productIsLarge>N</productIsLarge> <reported>T</reported> <EAN>5035048560044</EAN> <manufacturerPartNumber>BL4018-XJ</manufacturerPartNumber> <sizeWidth>80</sizeWidth> <sizeLength>130</sizeLength> <sizeHeight>110</sizeHeight> <weight>690</weight> <sizeMeasurementUnit>mm</sizeMeasurementUnit> <weightMeasurementUnit>g</weightMeasurementUnit> <dimensionalWeight>228</dimensionalWeight> <additionalAvailabilityInfo> </additionalAvailabilityInfo> <expiryDate>1900-01-01</expiryDate> <ETA></ETA> <incomingStock>0 </incomingStock> <mainCategoryTree>House and Garden </mainCategoryTree> <categoryTree>Tools - accessories </categoryTree> <subCategoryTree>Batteries</subCategoryTree> <Image_main>/Icecat/O9P0t7g7k0k0E1s6H7O4u1R3H7c757V9.jpg</Image_main> <Image_extra_1>/Icecat/O2N59732L0C0C1V6o7K4N143m7O7K7A8.jpg</Image_extra_1> <Image_extra_2>/Icecat/I4B7m9t9K000X1b6w7V471A3H7R737c8.jpg</Image_extra_2> <Image_extra_3>/Icecat/I1P2w3a2c0r0N116X7E4P1a3n7l7w7q9.jpg</Image_extra_3> <Image_extra_4>/Icecat/T9X096A3D0D0T1d6A7h481i3B7P7A8L0.jpg</Image_extra_4> <Image_extra_5>/Icecat/Q1D233T3K020Z10607c421L3N7Z7Q8n1.jpg</Image_extra_5> <Image_extra_6>/Icecat/Z2X2z2e5s03031B6G7r4j1Z2W4C9B926.jpg</Image_extra_6> <Product_type>Battery</Product_type> <Battery_technology>Lithium-Ion (Li-Ion)</Battery_technology> <Battery_capacity>2 Ah</Battery_capacity> <Battery_voltage>18 V</Battery_voltage> <Product_colour>Grey Black Orange</Product_colour> <Number_of_batteries_included>1 pc(s)</Number_of_batteries_included> </product> </Products>
解决方案
以下是实现目标转换的完整XSLT代码:
<?xml version="1.0" encoding="UTF-8"?> <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"/> <!-- 处理根节点Products --> <xsl:template match="Products"> <Products> <xsl:for-each select="Product"> <product> <!-- 提取Product节点的所有属性,转换为子元素 --> <xsl:for-each select="@*"> <xsl:element name="{name()}"> <xsl:value-of select="."/> </xsl:element> </xsl:for-each> <!-- 处理主图 --> <xsl:for-each select="Images/Image[@isMain='1']"> <Image_main> <xsl:value-of select="@url"/> </Image_main> </xsl:for-each> <!-- 处理副图,按顺序编号 --> <xsl:for-each select="Images/Image[@isMain='0']"> <xsl:element name="Image_extra_{position()}"> <xsl:value-of select="@url"/> </xsl:element> </xsl:for-each> <!-- 处理技术参数,将空格替换为下划线作为元素名,合并多值为空格分隔 --> <xsl:for-each select="TechnicalSpecification/Section/Attributes/Attribute"> <xsl:element name="{translate(@name, ' ', '_')}"> <xsl:for-each select="Values/Value"> <xsl:value-of select="@Name"/> <xsl:if test="position() != last()"> <xsl:text> </xsl:text> </xsl:if> </xsl:for-each> </xsl:element> </xsl:for-each> </product> </xsl:for-each> </Products> </xsl:template> </xsl:stylesheet>
关键实现说明
- 提取Product属性:通过
<xsl:for-each select="@*">遍历Product节点的所有属性,动态生成同名子元素,避免逐个手动编写。 - 区分主副图:
- 主图:筛选
@isMain='1'的Image节点,生成<Image_main>元素 - 副图:筛选
@isMain='0'的Image节点,用position()动态生成带编号的<Image_extra_n>元素
- 主图:筛选
- 处理技术参数:
- 将Attribute的
name属性中的空格替换为下划线,作为输出元素名(比如"Product type"转为Product_type) - 多值属性(如Product colour)将所有Value的Name值用空格连接后输出
- 将Attribute的
内容的提问来源于stack exchange,提问作者Sylwester Zabielski
相关产品推荐
相关产品推荐

