2

我有以下电子表格 XML:

<Workbook>
    <Worksheet ss:Name="Sheet1">
        <Table>
            <Row>
                <Cell><Data ss:Type="String">Parent</Data></Cell>
                <Cell><Data ss:Type="String">Child</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">A</Data></Cell>
                <Cell><Data ss:Type="String">B</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">A</Data></Cell>
                <Cell><Data ss:Type="String">C</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">B</Data></Cell>
                <Cell><Data ss:Type="String">D</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">B</Data></Cell>
                <Cell><Data ss:Type="String">E</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">C</Data></Cell>
                <Cell><Data ss:Type="String">F</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">C</Data></Cell>
                <Cell><Data ss:Type="String">G</Data></Cell>
            </Row>
        </Table>
    </Worksheet>
</Workbook>

我希望使用 Saxon XSLT 2.0 将其转换为以下格式:

<Something id="A">
    <Something id="B">
        <Something id="D"/>
        <Something id="E"/>
    </Something>
    <Something id="C">
        <Something id="F"/>
        <Something id="G"/>
    </Something>
</Something>

有人可以帮忙吗?我相信答案在于递归应用模板(尽管我希望 for-each 可以实现相同的效果)。

非常感谢。

更新:作为对 Navin 的回应,我一直在尝试 XSLT,它看起来像下面这样,但我担心我在叫错树(也许在我的组开始?):

<xsl:stylesheet 
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    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"
    xpath-default-namespace="urn:schemas-microsoft-com:office:spreadsheet"
    exclude-result-prefixes="o x ss html"
    >   

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="Workbook/Worksheet[@ss:Name='Sheet1']/Table">      
        <xsl:variable name="row_header" select="count(Row/Cell[.='Parent']/preceding-sibling::Row)+1"/>
        <xsl:apply-templates select="Row[position() > $row_header]">
            <xsl:with-param name="row_header" select="$row_header"/>
        </xsl:apply-templates>  
    </xsl:template>

    <xsl:template match="Row">
        <xsl:param name="row_header"/>
        <xsl:variable name="ChildId" select="Cell[count(ancestor::*/Row[$row_header]/Cell[.='Child']/preceding-sibling::Cell)+1]"/>
        <xsl:variable name="ParentId" select="Cell[count(ancestor::*/Row[$row_header]/Cell[.='Parent']/preceding-sibling::Cell)+1]"/>
        <xsl:for-each-group select="*" group-starting-with="Row">
            <Something id="{$ChildId}">
                <xsl:apply-templates select="current-group()[position() &gt; 1]" mode="Child">
                    <xsl:with-param name="ChildId" select="$ChildId"/>
                </xsl:apply-templates>
            </Something>
        </xsl:for-each-group>
    </xsl:template> 

    <xsl:template match="*" mode="Child">
        <xsl:param name="ChildId"/>
            <Something id="{$ChildId}"/>
    </xsl:template>

</xsl:stylesheet>
4

2 回答 2

2

可能有更好的 XSLT 2.0 方法,但这是在 XSLT 1.0 中的实现方式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:key name="kChildren" match="Row" use="Cell[2]/Data"/>
  <xsl:key name="kParent" match="Row" use="Cell[1]/Data "/>

  <xsl:template match="/">
    <xsl:apply-templates 
             select="*/*/*/*[position() != 1]
                            [not(key('kChildren', Cell[1]/Data))]
                            [generate-id() = 
                             generate-id(key('kParent', Cell[1]/Data)[1])]">
      <xsl:with-param name="idCell" select="1" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Row">
    <xsl:param name="idCell" select="2" />
    <Something id="{Cell[$idCell]/Data}">
      <xsl:apply-templates
        select="key('kParent', Cell[$idCell]/Data)
                      [generate-id() = 
                       generate-id(key('kChildren', Cell[2]/Data)[1])]" />
    </Something>
  </xsl:template>
</xsl:stylesheet>

在您的示例输入上运行时,结果是:

<Something id="A">
  <Something id="B">
    <Something id="D" />
    <Something id="E" />
  </Something>
  <Something id="C">
    <Something id="F" />
    <Something id="G" />
  </Something>
</Something>
于 2013-04-23T12:15:39.147 回答
1

像下面的 xslt 会做。(仅使用 xlt 1.0 版进行了尝试,mamesppace 存在一些问题。)假设第一行是标题,第一个单元格是父级,第二个是子级,这并不灵活。

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ss="Sheet1"
                >
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <xsl:variable name ="parent">
            <xsl:value-of select="//Row[2]/Cell[1]/Data"/>
        </xsl:variable>
        <Something id="{$parent}">
            <xsl:apply-templates select="//Row[Cell[position()=1 and Data=$parent]]" />
        </Something>

    </xsl:template>

    <xsl:template match="Row">

        <xsl:variable name ="child">
            <xsl:value-of select="Cell[2]/Data"/>
        </xsl:variable>
        <Something id="{$child}">
            <xsl:apply-templates select="//Row[Cell[position()=1 and Data=$child]]" />
        </Something>
    </xsl:template>
</xsl:styles

生成的输出是:

<?xml version="1.0"?>
<Something xmlns:ss="Sheet1" id="A">
  <Something id="B">
    <Something id="D"/>
    <Something id="E"/>
  </Something>
  <Something id="C">
    <Something id="F"/>
    <Something id="G"/>
  </Something>
</Something>
于 2013-04-23T11:36:18.513 回答