简体   繁体   English

如何使用xslt转换此xml

[英]How to transform this xml using xslt

I have an XML in the following format: 我有以下格式的XML:

<?xml version="1.0" encoding="utf-8"?>
<dataset  xmlns="http://developer.cognos.com/schemas/xmldata/1/"  xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
    <metadata>
          <item name="Col1" type="xs:string" length="14"/>
          <item name="Col2" type="xs:string" length="92"/>
          <item name="Col3" type="xs:string" length="66"/>
          <item name="Col4 With Space" type="xs:string" length="32"/>
    </metadata>
    <data>
        <row>
            <value>SomeVal1</value>
            <value>SomeVal2</value>
            <value>SomeVal3</value>
            <value>SomeVal4</value>
        </row>
        <row>
            <value>SomeVal11</value>
            <value>SomeVal22</value>
            <value>SomeVal33</value>
            <value>SomeVal44</value>
        </row>
    </data>
</dataset>

I want to transform it to this format: 我想将其转换为以下格式:

<?xml version="1.0" encoding="utf-8"?>
<dataset>
    <data>
        <row>
            <Col1 type="xs:string" length="14">SomeVal1</Col1>
            <Col2 type="xs:string" length="92">SomeVal2</Col2>
            <Col3 type="xs:string" length="66">SomeVal3</Col3>
            <Col4_With_Space type="xs:string" length="32">SomeVal4</Col4_With_Space>
        </row>
        <row>
            <Col1 type="xs:string" length="14">SomeVal11</Col1>
            <Col2 type="xs:string" length="92">SomeVal22</Col2>
            <Col3 type="xs:string" length="66">SomeVal33</Col3>
            <Col4_With_Space type="xs:string" length="32">SomeVal44</Col4_With_Space>
        </row>
    </data>
</dataset>

I've never used xslt before and I am out of my depth. 我以前从来没有使用过xslt,但我的能力不强。 I tried something like this (which doesn't work) but I'm stuck. 我尝试了类似的方法(不起作用),但被卡住了。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/>
    <xsl:template match="dataset">
        <xsl:for-each select="data/row">
            <Col1 select="1"/>
            <Col2 select="2"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

The reason for wanting to transform is SSIS "Data Flow" "XML Source" doesn't recognise the first format. 想要进行转换的原因是SSIS“数据流”“ XML源”无法识别第一种格式。 I'm trying to import data from an XML into a DB table. 我正在尝试将数据从XML导入数据库表。 "XML Source" works with the 2nd format but not the first. “ XML Source”适用于第二种格式,但不适用于第一种格式。

I think I should add, there is no guarantee XML metadata will always be the same, so transform needs to take the column names and types from the metadata, instead of hard-coding. 我想我应该补充一点,不能保证XML元数据总是相同的,因此transform需要从元数据中获取列名和类型,而不是硬编码。

I've never used xslt before and I am out of my depth. 我以前从来没有使用过xslt,但我的能力不强。

This is certainly not a task suitable for a beginner. 这当然不是适合初学者的任务。

As I mentioned in the comment to your question, your first problem is that your source XML places all its elements in a namespace. 正如我在对问题的评论中提到的那样,您的第一个问题是源XML将其所有元素放在命名空间中。 You need to declare the same namespace in your stylesheet, assign it a prefix and use that prefix to address the elements in the source XML. 您需要在样式表中声明相同的名称空间,为其分配一个前缀,然后使用该前缀来寻址源XML中的元素。

The other issue with your attempt is that you're not actually getting any data from the source XML. 尝试的另一个问题是您实际上没有从源XML获取任何数据。

<Col1 select="1"/>

will output the same static element for each row in your XML. 将为XML中的每一行输出相同的静态元素。

Now, the real complication here is getting the columns names and attributes from the metadata section and pairing them with the corresponding cell value from the current row. 现在,真正的麻烦在于从metadata部分获取列名和属性,并将它们与当前行中的相应单元格值配对。 This could be accomplished as follows: 这可以通过以下方式完成:

XSLT 1.0 XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cog="http://developer.cognos.com/schemas/xmldata/1/" 
exclude-result-prefixes="cog">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/cog:dataset">
    <xsl:variable name="cols" select="cog:metadata/cog:item" />
    <dataset>
        <data>
            <xsl:for-each select="cog:data/cog:row">
                <xsl:variable name="curr-row-cells" select="cog:value" />
                <row>
                    <xsl:for-each select="$cols">
                        <xsl:variable name="i" select="position()" />
                        <xsl:element name="{translate(@name, ' ', '_')}">
                            <xsl:copy-of select="@type | @length"/>
                            <xsl:value-of select="$curr-row-cells[$i]" />
                        </xsl:element>
                    </xsl:for-each>
                </row>
            </xsl:for-each>
        </data>
    </dataset>
</xsl:template>

</xsl:stylesheet>

Result 结果

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <data>
    <row>
      <Col1 type="xs:string" length="14">SomeVal1</Col1>
      <Col2 type="xs:string" length="92">SomeVal2</Col2>
      <Col3 type="xs:string" length="66">SomeVal3</Col3>
      <Col4_With_Space type="xs:string" length="32">SomeVal4</Col4_With_Space>
    </row>
    <row>
      <Col1 type="xs:string" length="14">SomeVal11</Col1>
      <Col2 type="xs:string" length="92">SomeVal22</Col2>
      <Col3 type="xs:string" length="66">SomeVal33</Col3>
      <Col4_With_Space type="xs:string" length="32">SomeVal44</Col4_With_Space>
    </row>
  </data>
</dataset>

Important: 重要:

The supplied column names are not necessarily valid XML element names. 提供的列名称不一定是有效的XML元素名称。 In this example, "Col4 With Space" contains spaces which I have translated to underscores - but there are many other potential pitfalls that may cause a name to be unusable and generate a fatal error. 在此示例中, "Col4 With Space"包含我已翻译为下划线的空格-但是还有许多其他潜在的陷阱,这些陷阱可能导致名称不可用并产生致命错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM