Search code examples
xmlxsltdtdsaxonxalan

How to get the unparsed entity attribute's value from XSLT?


I have a problem with XSLT and unparsed entity in XML. Here is a fictional scenario. First I got an XML file named doc.xml:

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

<!DOCTYPE document [
<!ELEMENT document (employee)*>
<!ELEMENT employee (lastname, firstname)>
<!ELEMENT lastname (#PCDATA)>
<!ELEMENT firstname (#PCDATA)>
<!NOTATION FOO SYSTEM 'text/xml'>
<!ENTITY ATTACHMENT SYSTEM 'attach.xml' NDATA FOO>
<!ATTLIST employee
       detail ENTITY #IMPLIED>
]>
<document>
    <employee detail="ATTACHMENT">
        <lastname>Bob</lastname>
        <firstname>Kevin</firstname>
    </employee>
</document>

In this XML file, I use an unparsed entity(NDATA) for the attribute "detail" of the element "employee". The attach.xml is:

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

<name>Bob Kevin</name>

Then i want to use XSLT to generate an output together with the attach.xml embedded. My XSLT file is named doc.xsl:

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="document">
<Document>
        <xsl:apply-templates select="employee"/>
</Document>
</xsl:template>

<xsl:template match="employee">
Employee is:  <xsl:value-of select="@detail"/>
</xsl:template>

</xsl:stylesheet>

Finally, I run using Xalan 2.7.1 :

java -jar xalan.jar -IN doc.xml -XSL doc.xsl -OUT docout.xml

The output is:

<?xml version="1.0" encoding="UTF-8"?>
<Document>
Employee is:  ATTACHMENT
</Document>

This is not what i want. I want the output looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Document>
Employee is:  <name>Bob Kevin</name>
</Document>

How should I rewrite the XSLT script to get the correct result?


Solution

  • The solution in XSLT 2.0:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="document">
    <Document>
            <xsl:apply-templates select="employee"/>
    </Document>
    </xsl:template>
    
    <xsl:template match="employee">
    Employee is:  <xsl:value-of select=
    "unparsed-text(unparsed-entity-uri(@detail))"/>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Do note the following:

    1. The use of the XSLT functions unparsed-text() and unparsed-entity-uri().

    2. The text of the attach.xml file will be escaped in the output. If you want to see it unescaped, use the "cdata-section-elements" attribute of the <xsl:output/> instruction.