Search code examples
xmlxsltattributesxslt-2.0

Need to fetch the attribute values from the XSL


I have worked on generating the elements and attributes names along with output elements and attributes. Here I'm converting input xml to docbook xml by using Oxygen XML Editor 18.0.

I'm having input xml like:

<Section1 id="1">
   <Section1Heading>Section 1</Section1Heading>
  <Section2 id="2">
    <Section2Heading>Heading</Section2Heading>
    <Para>other.</Para>
  </Section2>
</Section1>

XSL I'm having:

<xsl:template match="Section1">
   <sect1>
       <xsl:attribute name="label">
          <xsl:value-of select="@id"/>
       </xsl:attribute>
      <xsl:apply-templates/>
   </sect1>
</xsl:template>

<xsl:template match="Section1Heading | Section2Heading">
    <title>
        <xsl:apply-templates/>
    </title>
</xsl:template>

<xsl:template match="Section2">
   <sect2>
      <xsl:attribute name="label">
         <xsl:value-of select="@id"/>
      </xsl:attribute>
      <xsl:apply-templates/>
   </sect2>
</xsl:template>

<xsl:template match="Para">
   <para>
      <xsl:apply-templates/>
   </para>
</xsl:template>

Tried the XSL like below:

  <xsl:param name="field-sep" as="xs:string">,</xsl:param>
  <xsl:param name="line-sep" as="xs:string" select="'&#10;'"/>

  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
      <xsl:value-of select="concat('Input XML', $field-sep, 'Result XML')"/>
      <xsl:value-of select="$line-sep"/>
      <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="xsl:template[@match]">
    <xsl:value-of 
       select="for $pattern in tokenize(@match, '\s*\|\s*')
               return concat($pattern, $field-sep, node-name(current()/*[1]))"
       separator="{$line-sep}"/>
       <xsl:value-of select="$line-sep"/>
  </xsl:template>

Expected output would be:

Input XML,Result XML
Section1,sect1
@id,label
Section1Heading,title
Section2Heading,title
Section2,sect2
@id,label
Para,para

Solution

  • I think this would produce the output you need, although it relies on your input XSLT having a very restricted structure (e.g. It assumes the xsl:attribute always contains xsl:value-of)

    <xsl:template match="xsl:template[@match]">
      <xsl:variable name="current" select="." />
      <xsl:for-each select="tokenize(@match, '\s*\|\s*')">
        <xsl:value-of select="concat(., $field-sep, node-name($current/*[1]))" />
        <xsl:value-of select="$line-sep"/>
        <xsl:for-each select="$current/*[1]/xsl:attribute">
          <xsl:value-of select="concat(xsl:value-of[1]/@select, $field-sep, @name)" />
          <xsl:value-of select="$line-sep"/>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:template>