当兄弟姐妹包含2个子元素时,XSL XPath会有所帮助

时间:2015-03-19 20:32:21

标签: xml xslt xpath

我在提出XPath语句时遇到问题,该语句将帮助我从Excel XML创建目录。

这是我的基本Excel XML结构:

<Table>
<Row>
    <Cell>
        <Data ss:Type="String">Title 1</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle1</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename1</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle2</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename2</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle3</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename3</Data>
    </Cell>
</Row>
<Row>
    <Cell>
        <Data ss:Type="String">Title 2</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle1</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename1</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle2</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename2</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle3</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename3</Data>
    </Cell>
</Row>
<Row>
    <Cell ss:Index="2">
        <Data ss:Type="String">Subtitle4</Data>
    </Cell>
    <Cell>
        <Data ss:Type="String">Filename4</Data>
    </Cell>
</Row>

如上所示,我有两个标题,每个标题都有一个Cell元素,我需要能够抓住包含两个Cell元素的以下兄弟。我需要输出看起来像:

<ul class="nav">
  <li class="sub">
    <a href="javascript:void(0);">Title 1</a>
    <ul>
        <li>
            <a href="javascript:void(0);" data-src="Filename1">Subtitle1</a>
        </li>
        <li>
            <a href="javascript:void(0);" data-src="Filename2">Subtitle2</a>
        </li>
        <li>
            <a href="javascript:void(0);" data-src="Filename3">Subtitle3</a>
        </li>
    </ul>
  </li>
  <li class="sub">
    <a href="javascript:void(0);">Title 2</a>
    <ul>
        <li>
            <a href="javascript:void(0);" data-src="Filename1">Subtitle1</a>
        </li>
        <li>
            <a href="javascript:void(0);" data-src="Filename2">Subtitle2</a>
        </li>
        <li>
            <a href="javascript:void(0);" data-src="Filename3">Subtitle3</a>
        </li>
        <li>
            <a href="javascript:void(0);" data-src="Filename4">Subtitle4</a>
        </li>
    </ul>
  </li>
</ul>

我会提供一些代码,但恐怕我没有走得太远。对于XSLT,我是一个菜鸟。

2 个答案:

答案 0 :(得分:2)

XSLT 1.0 解决方案

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

    <xsl:template match="Table">
        <ul class="nav">
            <xsl:apply-templates select="Row[count(Cell)=1]"/>
        </ul>
    </xsl:template>

    <xsl:template match="Row[count(Cell)=1]">
        <li class="sub">
            <a href="javascript:void(0);"><xsl:value-of select="Cell/Data"/></a>
            <ul>
                <xsl:variable name="heading" select="."/>
                <xsl:apply-templates 
                      select="following-sibling::Row[Cell[2]]
                                [generate-id(preceding-sibling::Row[count(Cell)=1][1]) = 
                                                 generate-id($heading)]"/>
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="Row[Cell[2]]">
        <li>
            <a href="javascript:void(0);" data-src="{ Cell[2]/Data }">
              <xsl:value-of select="Cell[1]/Data"/>
            </a>
        </li>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:2)

这是使用xsl:key的另一种方式(复制 Mads Hansen 的答案):

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

    <xsl:key name="element" match="Row[Cell[2]]" use="generate-id(preceding::Row[count(Cell) = 1][1])"/>

    <xsl:template match="Table">
        <ul class="nav">
            <xsl:apply-templates select="Row[count(Cell)=1]"/>
        </ul>
    </xsl:template>

    <xsl:template match="Row[count(Cell)=1]">
        <li class="sub">
            <a href="javascript:void(0);">
                <xsl:value-of select="Cell/Data"/>
            </a>
            <ul>
                <xsl:apply-templates  select="key('element', generate-id())"/>
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="Row[Cell[2]]">
        <li>
            <a href="javascript:void(0);" data-src="{ Cell[2]/Data }">
                <xsl:value-of select="Cell[1]/Data"/>
            </a>
        </li>
    </xsl:template>

</xsl:stylesheet>