1

I need to format XML input using XSL to obtain more convenient structure. As a next step of processing i want to transform it to HTML. Suppose i have the following input: (0)

<list>
<item item-id="1" second-item-id="1" third-item-id="1"/>
<item item-id="1" second-item-id="1" third-item-id="2"/>
<item item-id="1" second-item-id="2" third-item-id="1"/>
<item item-id="1" second-item-id="3" third-item-id="1"/>

<item item-id="2" second-item-id="1" third-item-id="1"/>
<item item-id="2" second-item-id="1" third-item-id="2"/>
<item item-id="2" second-item-id="1" third-item-id="3"/>
<item item-id="2" second-item-id="2" third-item-id="1"/>

<item item-id="3" second-item-id="1" third-item-id="1"/>
<item item-id="3" second-item-id="1" third-item-id="2"/>
<item item-id="3" second-item-id="1" third-item-id="3"/>
<item item-id="3" second-item-id="1" third-item-id="4"/>
</list>

and the following XSL template: (1)

<?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:key name="itemKey" match="item" use="@item-id"/>
  <xsl:key name="secondItemKey" match="item" use="concat(@item-id, '|', @second-item-id)"/>

  <xsl:template match="list">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="item[generate-id() = generate-id(key('itemKey', @item-id)[1])]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item">
    <item item-id="{@item-id}">
      <xsl:apply-templates select="key('itemKey', @item-id)[generate-id() = generate-id(key('secondItemKey', concat(@item-id, '|', @second-item-id))[1])]" mode="evt"/>
    </item>
  </xsl:template>

  <xsl:template match="item" mode="evt">
    <second-item second-item-id="{@second-item-id}">
      <xsl:apply-templates select="key('secondItemKey', concat(@item-id, '|', @second-item-id))" mode="bus"/>
    </second-item>
  </xsl:template>

  <xsl:template match="item" mode="bus">
    <third-item third-item-id="{@third-item-id}"/>
  </xsl:template>    

</xsl:stylesheet>

it gives me pretty fine XML: (2)

<?xml version="1.0"?>
<list>
    <item item-id="1">
        <second-item second-item-id="1">
            <third-item third-item-id="1"/>
            <third-item third-item-id="2"/>
        </second-item>
        <second-item second-item-id="2">
            <third-item third-item-id="1"/>
        </second-item>
        <second-item second-item-id="3">
            <third-item third-item-id="1"/>
        </second-item>
    </item>
    <item item-id="2">
        <second-item second-item-id="1">
            <third-item third-item-id="1"/>
            <third-item third-item-id="2"/>
            <third-item third-item-id="3"/>
        </second-item>
        <second-item second-item-id="2">
            <third-item third-item-id="1"/>
        </second-item>
    </item>
    <item item-id="3">
        <second-item second-item-id="1">
            <third-item third-item-id="1"/>
            <third-item third-item-id="2"/>
            <third-item third-item-id="3"/>
            <third-item third-item-id="4"/>
        </second-item>
    </item>
</list>

i have another XSL which transforms XML #2 to html:

<?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" method="html"/>
    <xsl:template match="list">
        <xsl:for-each select="item">
            <h2><xsl:value-of select="concat(local-name(),' ',@item-id)"/></h2>
            <ul>
                <xsl:for-each select="second-item">
                    <li><xsl:value-of select="concat(local-name(),' ',@second-item-id)"/></li>
                    <ul>
                        <xsl:for-each select="third-item">
                            <li><xsl:value-of select="concat(local-name(),' ',@third-item-id)"/></li>
                        </xsl:for-each>
                    </ul>
                </xsl:for-each>
            </ul>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

So here is the question: I want to process input xml with both of tempaltes (or merged one) in one step. How can i do it?

Thanks in advance.

3

1 Answer 1

1

If you're happy with just merging them together, then this should accomplish the job of both at the same time:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output indent="yes"/>

  <xsl:key name="itemKey" match="item" use="@item-id"/>
  <xsl:key name="secondItemKey" match="item" use="concat(@item-id, '|', @second-item-id)"/>

  <xsl:template match="list">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="item[generate-id() = generate-id(key('itemKey', @item-id)[1])]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item">
    <h2>
      <xsl:value-of select="concat('item ', @item-id)"/>
    </h2>
    <ul>
      <xsl:apply-templates select="key('itemKey', @item-id)[generate-id() = generate-id(key('secondItemKey', concat(@item-id, '|', @second-item-id))[1])]" mode="evt"/>
    </ul>
  </xsl:template>

  <xsl:template match="item" mode="evt">
    <li>
      <xsl:value-of select="concat('second-item ', @second-item-id)"/>
    </li>
    <ul>
      <xsl:apply-templates select="key('secondItemKey', concat(@item-id, '|', @second-item-id))" mode="bus"/>
    </ul>
  </xsl:template>

  <xsl:template match="item" mode="bus">
    <li>
      <xsl:value-of select="concat('third-item ', @third-item-id)"/>
    </li>
  </xsl:template>

</xsl:stylesheet>

There is an easy enough way to have them both in one XSLT and run one after the other, but the approach I have in mind would require the use of the node-set() function which is unfortunately in a different namespace for each XSLT implementation. Which XSLT processor are you using?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.