开发者

XSLT - how to parse xml with recursive elements to Eclipse toc.xml?

I have the following XML:

<HTML>
  <HEAD>
    <META name="GENERATOR" content="Microsoft HTML Help Workshop 4.1" />
    <!-- Sitemap 1.0 -->
  </HEAD>
  <BODY>
    <OBJECT type="text/site properties">
      <param name="FrameName" value="contents" />
    </OBJECT>
    <UL>
      <LI>
        <OBJECT type="text/sitemap">
          <param name="Name" value="Title1" />
          <param name="Local" value="Ref1" />
        </OBJECT>
        <UL>
          <LI>
            <OBJECT type="text/sitemap">
              <param name="Name" value="Title 2" />
              <param name="Local" value="Ref2" />
            </OBJECT>
            <UL>
              <LI>
                <OBJECT type="text/sitemap">
                  <param name="Name" value="Title3" />
                  <param name="Local" value="Ref3" />
                </OBJECT>
              </LI>
              <LI>
                <OBJECT type="text/sitemap">
                  <param name="Name" value="Title4" />
                  <param name="Local" value="Ref4" />
                </OBJECT>
              </LI>
            </UL>
          </LI>
          <LI>
            <OBJECT type="text/sitemap">
              <param name="Name" value="Title5" />
              <param name="Local" value="Ref5" />
            </OBJECT>
          </LI>
        </UL>
      </LI>
      <LI>
        <OBJECT type="text/sitemap">
          <param name="Name" value="Title6" />
          <param name="Local" value="Ref6" />
        </OBJECT>
      </LI>
    </UL>
  </BODY>
</HTML>

I need to transform it to an "Eclipse Help" format toc.xml file, like this:

<toc label="Sample Tab开发者_StackOverflow社区le of Contents">
  <topic label="Title1"  href="Ref1"> 
    <topic label="Title2" href="Ref2">
      <topic label="Title3" href="Ref3"/>
        <topic label="Title4" href="Ref4"/>
      </topic> 
      <topic label="Title5" href="Ref5">
    </topic> 
  </topic>
  <topic label="Title6" href="Ref6"/>
</toc>

I tried to create the following XSLT, which didn't work:

<?xml version="1.0" encoding="utf-8"?>
<?altova_samplexml D:\Documents and Settings\oshecht\Desktop\XSL\Copy of toc.xml?>
<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" />

  <xsl:template match="/">
    <toc>
      <xsl:apply-templates select="//LI" />
    </toc>
  </xsl:template>

  <xsl:template match="//LI">
    <topic>
      <xsl:apply-templates select="OBJECT/param" mode="val" />
      <xsl:apply-templates select="OBJECT/param" mode="ref" />
      <xsl:apply-templates select="/UL/LI" />
      <!--xsl:apply-templates select="//UL//LI"  mode="subelement" /-->
    </topic>
  </xsl:template>

  <xsl:template match="OBJECT/param" mode="val">
    <xsl:if test="@name = 'Name'">
      <xsl:attribute name="label">
        <xsl:value-of select="@value" />
      </xsl:attribute>
    </xsl:if>
  </xsl:template>

  <xsl:template match="OBJECT/param" mode="ref">
    <xsl:if test="@name = 'Local'">
      <xsl:attribute name="href">
        <xsl:value-of select="@value" />
      </xsl:attribute>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Can you please advise?

Thanks:)


I think the following does what you want:

<xsl:template match="BODY">
    <toc label="Sample Table of Contents">
        <xsl:apply-templates select="UL/LI/OBJECT"/>
  </toc>
</xsl:template>

<xsl:template match="OBJECT">
  <topic label="{param[@name='Name']/@value}" href="{param[@name='Local']/@value}">
    <xsl:apply-templates select="following-sibling::UL/LI/OBJECT"/>
  </topic>
</xsl:template>


Your main problem is this line:

<xsl:apply-templates select="//LI"  />

This produces a list of all <LI> elements in the input, and thus creates a flat output list. You can use the built-in recursion and "move with the flow", like this:

<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" />

  <xsl:template match="BODY">
    <toc>
      <xsl:apply-templates select="OBJECT" />
      <xsl:apply-templates select="UL" />
    </toc>
  </xsl:template>

  <xsl:template match="UL">
    <xsl:apply-templates select="LI" />
  </xsl:template>

  <xsl:template match="LI">
    <topic>
      <xsl:apply-templates select="OBJECT" />
      <xsl:apply-templates select="UL" />
    </topic>
  </xsl:template>

  <xsl:template match="OBJECT">
    <xsl:apply-templates select="param" />
  </xsl:template>

  <xsl:template match="OBJECT/param">
    <xsl:variable name="attrName">
      <xsl:choose>
        <xsl:when test="@name = 'FrameName'">label</xsl:when>
        <xsl:when test="@name = 'Name'">label</xsl:when>
        <xsl:when test="@name = 'Local'">href</xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:if test="$attrName != ''">
      <xsl:attribute name="{$attrName}">
        <xsl:value-of select="@value" />
      </xsl:attribute>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

The output produced is:

<?xml version="1.0" encoding="utf-8"?>
<toc label="contents">
  <topic label="Title1" href="Ref1">
    <topic label="Title 2" href="Ref2">
      <topic label="Title3" href="Ref3"></topic>
      <topic label="Title4" href="Ref4"></topic>
    </topic>
    <topic label="Title5" href="Ref5"></topic>
  </topic>
  <topic label="Title6" href="Ref6"></topic>
</toc>

Note that I replaced your "mode" templates whith an <xsl:choose>. The rest is fairly obvious, I think.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜