XSLT to generate html tags specified in XML

2019-02-19 11:05发布

问题:

So this may be a strange request but I'll give it a go. I have an xml document

<?xml version="1.0" encoding="utf-8" ?>
<Page>
  <ID>Site</ID>
  <Object>
    <ID>PostCode</ID>
    <Type>div</Type>
    <Class>display-label</Class>
    <Value>PostCode</Value>
  </Object>
  <Object>
    <ID>PostCodeValue</ID>
    <Type>div</Type>
    <Class>display-field</Class>
    <Value>$PostCode</Value>
  </Object>
</Page>

and I'm using this XSL to transform it into a html page

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="yes"/>
  <xsl:template match="/">
    <html>
      <head>
      </head>
      <body>
        <xsl:for-each select="Page/Object">
          &lt;<xsl:value-of select="Type"/>&gt;
          <xsl:value-of select="Value"/>
          &lt;/<xsl:value-of select="Type"/>&gt;
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

As you can see I'm trying to generate the correct html tag dependent on the type node in the xml. The problem is "<" isn't accepted in the xsl and encoding it stops it from being recognised as a tag.

Any suggestions how I'd go about this?

Thanks in advance

回答1:

Use xsl:element to create an element node in the output document.

<xsl:element name="{Type}" >
<xsl:value-of select="Value"/>
</xsl:element>

Note: the curly braces in the name attribute may look strange, if you aren't familiar. It is an Attribute Value Template used to evaluate an XPATH expression inside of an attribute declaration.

Applied to your stylesheet:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="yes"/>
  <xsl:template match="/">
    <html>
      <head>
      </head>
      <body>
        <xsl:for-each select="Page/Object">
            <xsl:element name="{Type}" >
                <xsl:value-of select="Value"/>
            </xsl:element>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>


回答2:

you need to wrap your "<" in a text node with disable-output-escaping like this:

<?xml version="1.0" encoding="utf-8"?><!-- DWXMLSource="temp.xml" -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="html" indent="yes"/>
  <xsl:template match="/">
    <html>
      <head>
      </head>
      <body>
        <xsl:for-each select="Page/Object">
          <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="Type"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
          <xsl:value-of select="Value"/>
          <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="Type"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>


标签: xslt