ljk
ljk

Reputation: 628

how to embed xsl into xml file

I have a file test.xml

<?xml version="1.0 encoding="UTF-8">

<foo name="1" b="2">
  <bar name="11" b="22">
    <baz name="111" b="222"/>
    <baz name="112" b="223"/>
    ...
  </bar>
</foo>

and a XSLT file styles.xsl

 <?xml version="1.0" encoding="utf-8">
 <xsl:stylesheet version=1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
   <html>
     <body>
       <!--xslt-->
    </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

I can get the page to display correctly by adding this line, <?xml-stylesheet type="text/xsl" href="styles.xsl"?>, in test.xml. Now I'm trying to combine both files into one .xml file to be opened more conveniently. I tried merging the content of the two XML documents but that didn't work:

newtest.xml

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

   </html>
 </xsl:template>
</xsl:stylesheet>

Following steps on other SO threads returns either blank or unformatted page

Did I miss anything?

Upvotes: 1

Views: 4615

Answers (1)

Tim C
Tim C

Reputation: 70648

An XSLT document is also a well-formed XML document. XSLT is used to transform XML documents, and so you can in theory apply XSLT to itself.

Suppose your current XSLT looked like this

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
    <xsl:output method="html" omit-xml-declaration="yes"/>

    <xsl:template match="foo">
        <h1><xsl:value-of select="@name" /></h1>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="bar">
        <h2><xsl:value-of select="@name" /></h2>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="baz">
        <p><xsl:value-of select="@name" /></p>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates select="//foo" />
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Rather than embedding the XSLT into your test.xml, you can instead embed your XML into the XSLT, but then save it as your XML file. One way to do this is create a dummy namespace, and your XML as an element in the XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:my="my"
     exclude-result-prefixes="xsl my">
<my:embeddedXML>
    <foo name="1" b="2">
      <bar name="11" b="22">
        <baz name="111" b="222"/>
        <baz name="112" b="223"/>
      </bar>
    </foo>
</my:embeddedXML>

Then instead of doing <xsl:apply-templates select="//foo" />, replace it with this

<xsl:apply-templates />

But you would also need a template to ignore the xsl: elements in the "input" XML

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

    <xsl:template match="xsl:*" />

Then just add this line to the top of it, and save this file as Test.xml:

<?xml-stylesheet type="text/xsl" href="Test.xml"?>

So, effectively the XML is referencing itself to get the XSLT.

Try this XML/XSLT:

Test.xml

<?xml-stylesheet type="text/xsl" href="Test.xml"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl my" xmlns:my="my">
    <xsl:output method="html" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*" />

    <my:embeddedXML>
        <foo name="1" b="2">
          <bar name="11" b="22">
            <baz name="111" b="222"/>
            <baz name="112" b="223"/>
          </bar>
        </foo>
    </my:embeddedXML>

    <xsl:template match="foo">
        <h1><xsl:value-of select="@name" /></h1>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="bar">
        <h2><xsl:value-of select="@name" /></h2>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="baz">
        <p><xsl:value-of select="@name" /></p>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates />
            </body>
        </html>
    </xsl:template>

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

    <xsl:template match="xsl:*" />
</xsl:stylesheet>

Note that this XSLT could still be applied to other XML files if required

Upvotes: 3

Related Questions