xml - 将 XML 子项导入为 Excel 中的列

标签 xml excel vba xslt

我有几个大型 XML 文件需要将其转换为 Excel 电子表格。一些数据是嵌套的,当我导入 Excel 时,它会为每个子值创建额外的行。我想创建一列来处理子项,因此每个项目只有一行。以下是 XML 示例:

<Items>
    <Item MaintenanceType="C">
      <PartNumber>ABC123</PartNumber>
      <BrandLabel>Brand X</BrandLabel>
      <Descriptions>
        <Description MaintenanceType="C" DescriptionCode="DES" LanguageCode="EN" Sequence="1">This is a short description</Description>
        <Description MaintenanceType="C" DescriptionCode="EXT" LanguageCode="EN" Sequence="1">This is a little longer description</Description>
        <Description MaintenanceType="C" DescriptionCode="MKT" LanguageCode="EN" Sequence="1">This is a reallllllllllly long description</Description>
        <Description MaintenanceType="C" DescriptionCode="ASC" LanguageCode="EN" Sequence="1">Another Description</Description>
        <Description MaintenanceType="C" DescriptionCode="SHO" LanguageCode="EN" Sequence="1">ShortDesc</Description>
      </Descriptions>
      <Prices>
        <Pricing MaintenanceType="C" PriceType="LST">
          <PriceSheetNumber>J16</PriceSheetNumber>
          <CurrencyCode>USD</CurrencyCode>
          <EffectiveDate>2016-01-05</EffectiveDate>
          <Price UOM="PE">191.0000</Price>
        </Pricing>
        <Pricing MaintenanceType="C" PriceType="RET">
          <PriceSheetNumber>J16</PriceSheetNumber>
          <CurrencyCode>USD</CurrencyCode>
          <EffectiveDate>2016-01-05</EffectiveDate>
          <Price UOM="PE">191.0000</Price>
        </Pricing>
        <Pricing MaintenanceType="C" PriceType="RMP">
          <PriceSheetNumber>J16</PriceSheetNumber>
          <CurrencyCode>USD</CurrencyCode>
          <EffectiveDate>2016-01-05</EffectiveDate>
          <Price UOM="PE">181.4500</Price>
        </Pricing>
      </Prices>
      <DigitalAssets>
        <DigitalFileInformation MaintenanceType="C" LanguageCode="EN">
          <FileName>itemimage.jpg</FileName>
          <AssetType>P07</AssetType>
          <FileType>JPG</FileType>
          <Representation>R</Representation>
          <FileSize>76</FileSize>
          <Resolution>300</Resolution>
          <ColorMode>RGB</ColorMode>
          <Background>WHI</Background>
          <OrientationView>ANG</OrientationView>
          <AssetDimensions UOM="PX">
            <AssetHeight>1367</AssetHeight>
            <AssetWidth>1500</AssetWidth>
          </AssetDimensions>
          <URI>http://www.itemimageassets.xcom/ImgVDHR/BrandX/ABC123.jpg</URI>
        </DigitalFileInformation>
      </DigitalAssets>
    </Item>
</Items>

我创建的 XSLT 是这样的(我知道这是错误的,但不知道为什么):

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
    xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:user="urn:my-scripts"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" > 

    <xsl:template match="/">
        <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
            xmlns:o="urn:schemas-microsoft-com:office:office"
            xmlns:x="urn:schemas-microsoft-com:office:excel"
            xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
            xmlns:html="http://www.w3.org/TR/REC-html40">
            <xsl:apply-templates/>
        </Workbook>
    </xsl:template>

    <xsl:template match="/*">
        <Worksheet>
            <Table x:FullColumns="1" x:FullRows="1">
                <Row>
                    <xsl:for-each select="/PIES/Items/Item">
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="ItemLevelGTIN/text()"/>
                        </Data></Cell>
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="PartNumber/text()"/>
                        </Data></Cell>
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="SubBrandLabel/text()"/>
                        </Data></Cell>
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="Descriptions/Description/text()"/>
                        </Data></Cell>
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="Descriptions/Description/text()"/>
                        </Data></Cell>
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="Prices/Pricing/Price/text()"/>
                        </Data></Cell>
                        <Cell><Data ss:Type="String">
                            <xsl:value-of select="Prices/Pricing/Price/text()"/>
                        </Data></Cell>
                    </xsl:for-each>     
                </Row>
            </Table>
        </Worksheet>
    </xsl:template>
</xsl:stylesheet>

最佳答案

作为一种开放式文件结构,XML 树可以为设计者留下许多维度。然而,诸如电子表格或数据库表之类的表格结构是二维的(逐行),因此相应的 XML 必须是为每一行设置的一个子级别:

<data> 
  <row>
    <col>data</col>
    <col>data</col>
    <col>data</col>
    <col>data</col>
    <col>data</col>
   </row>
</data>

因此,请相应地构建 XSLT,将重复元素 Item 重新设置为扁平化的单级子元素集。下面走下<Item>节点使用 XPath 表达式根据属性值选择嵌套子节点。 <xsl:value-of>用于检索仅包含在新标签名称中的文本值,而 <xsl:copy-of>复制现有标签名称和文本值。

XSLT (另存为 .xsl 文件)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />

  <xsl:template match="Items">
    <xsl:copy>
      <xsl:apply-templates select="Item"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Item">
    <xsl:copy>      
      <xsl:copy-of select="PartNumber"/>
      <xsl:copy-of select="BrandLabel"/>
      <ShortDescription><xsl:value-of select="Descriptions/Description[@DescriptionCode='DES']"/></ShortDescription>      
      <LongDescription><xsl:value-of select="Descriptions/Description[@DescriptionCode='EXT']"/></LongDescription>
      <Price_LST><xsl:value-of select="Prices/Pricing[@PriceType='LST']/Price"/></Price_LST>
      <Price_RMP><xsl:value-of select="Prices/Pricing[@PriceType='RMP']/Price"/></Price_RMP>
      <xsl:copy-of select="DigitalAssets/DigitalFileInformation/*[local-name()!='AssetDimensions']"/>
      <xsl:copy-of select="DigitalAssets/DigitalFileInformation/AssetDimensions/*"/>      
    </xsl:copy>
  </xsl:template>

</xsl:transform>

VBA (使用 MSXML 库)

Public Sub RunXSLT()
    ' REFERENCE Microsoft XML, v6.0
    Dim xmlDoc As New MSXML2.DOMDocument60, xslDoc As New MSXML2.DOMDocument60, newDoc As New MSXML2.DOMDocument60

    xmlDoc.Load "C:\Path\To\Input.xml"
    xmlDoc.async = False

    xslDoc.Load "C:\Path\To\XSLTScript.xsl"
    xslDoc.async = False

    xmlDoc.transformNodeToObject xslDoc, newDoc
    newDoc.Save "C:\Path\To\Output.xml"

    Set newDoc = Nothing: Set xslDoc = Nothing: Set xmlDoc = Nothing

    ' IMPORT XML INTO NEW WORKBOOK
    Workbooks.OpenXML "C:\Path\To\Output.xml", , xlXmlLoadImportToList          
End Sub

输出

XML 转换

<?xml version="1.0" encoding="UTF-8"?>
<Items>
    <Item>
        <PartNumber>ABC123</PartNumber>
        <BrandLabel>Brand X</BrandLabel>
        <ShortDescription>This is a short description</ShortDescription>
        <LongDescription>This is a little longer description</LongDescription>
        <Price_LST>191.0000</Price_LST>
        <Price_RMP>181.4500</Price_RMP>
        <FileName>itemimage.jpg</FileName>
        <AssetType>P07</AssetType>
        <FileType>JPG</FileType>
        <Representation>R</Representation>
        <FileSize>76</FileSize>
        <Resolution>300</Resolution>
        <ColorMode>RGB</ColorMode>
        <Background>WHI</Background>
        <OrientationView>ANG</OrientationView>
        <URI>http://www.itemimageassets.xcom/ImgVDHR/BrandX/ABC123.jpg</URI>
        <AssetHeight>1367</AssetHeight>
        <AssetWidth>1500</AssetWidth>
    </Item>
</Items>

Excel 表格导入

Excel Table Import

关于xml - 将 XML 子项导入为 Excel 中的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41450460/

相关文章:

xml - 我的 XSLT 中有什么错误?

C# WCF - 创建自定义消息内容

excel - 如何在不自动连接的情况下将数据导入Excel?

excel - 输入框避免空白条目

vba - 仅允许 sub 在另一个已运行 VBA 后运行

vba - 如何重置Excel垂直滚动条长度(不关闭,然后重新打开工作簿)

.net - 序列化为 XML 片段 - 而不是 XML 文档

java - JAXB 不创建成员变量和 getter 和 setter

sql-server - 基于 Excel 列列表筛选 SQL View 的 Power Query

vba - Excel 不会显示工作簿工作表