0

If I have

<p>!!!This should be a note</p>

is it possible to convert the <p> tags to <note> tags using XSL (maybe using the !!! as an identifier?). Note that there would be other <p> tags that I wouldn't want to be converted. So the result would be

<note>!!!This should be a note</note>

or

<note>This should be a note</note>

Also, if I have

<p>This is an apiname</p>

and I want to use XSL to surround 'apiname' with <apiname> tags, example:

<p>This is an <apiname>apiname</apiname></p>

is there a way to do this?

I'm using DITA Open Toolkit to write Markdown, which is then converted to XML behind the scenes. Then, XSL is applied to the XML to display HTML and other formats. This is why I can't just update the XML from the source.

2 Answers2

1

To convert only p elements that start with !!! to note elements, you could do simply:

XSLT 1.0

<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:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="p[starts-with(., '!!!')]">
    <note>
        <xsl:apply-templates/>
    </note>
</xsl:template>

</xsl:stylesheet>

If you also want to remove the !!! identifier, change the 2nd template to:

<xsl:template match="p[starts-with(., '!!!')]">
    <note>
        <xsl:value-of select="substring-after(., '!!!')" />
    </note>
</xsl:template>

I suggest you ask a separate question regarding the apiname problem, and clarify:

  1. What exactly is apiname? Is it the literal string "apiname"?
  2. Can a p contain more than one occurrence of apiname?
  3. Which version of XSLT does your processor support?
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
-1

is it possible to convert the <p> tags to <note> tags using XSL?

Yes. You can use the following template:

<xsl:template match="p">
  <xsl:element name="note">
    <xsl:apply-templates select="node()|@*" />
  </xsl:element>
</xsl:template>   

If you want to transform only the <p> elements whose text() content starts with "!!!", use

<xsl:template match="p[starts-with(.,'!!!')]">   ...

and I want to use XSL to surround 'apiname' with tags

Also yes, use the following template:
Remark: you can't use a global variable in a template matching rule in XSLT-1.0

<xsl:variable name="api_replace" select="'apinamereplacement'" />
<xsl:variable name="api" select="'apiname'" />

<xsl:template match="p[contains(text(),'apiname')]">
  <xsl:copy>
    <xsl:copy-of select="@*" />
    <xsl:value-of select="substring-before(text(),$api)" />
    <xsl:element name="{$api_replace}">
      <xsl:value-of select="$api" />
    </xsl:element>
    <xsl:value-of select="substring-after(text(),$api)" />
  </xsl:copy>
</xsl:template>

A complete template could look like this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name="api_replace" select="'apinamereplacement'" />
  <xsl:variable name="api" select="'apiname'" />
  
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="p">
    <xsl:element name="note">
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>
  
  <xsl:template match="p[contains(text(),'apiname')]">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:value-of select="substring-before(text(),$api)" />
      <xsl:element name="{$api_replace}">
        <xsl:value-of select="$api" />
      </xsl:element>
      <xsl:value-of select="substring-after(text(),$api)" />
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>
Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19
zx485
  • 28,498
  • 28
  • 50
  • 59