views:

1007

answers:

3

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?

+1  A: 

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.

Dimitre Novatchev
I got a warning in Saxon-B 9.1.0.5, change stylesheet to version="2.0" works. Thanks again!
jscoot
@jscoot: Thanks, I corrected this accidental mistake from my answer.
Dimitre Novatchev
A: 

Thank you, Dimitre Novatchev. According to your answer, i got my result in XSLT 1.0. For those who may be interested, please refer to http://www.xml.com/lpt/a/1243 for a discussion. Here is my solution:

<?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:copy-of select="document(unparsed-entity-uri(@detail))"/>
</xsl:template>

</xsl:stylesheet>

Note the the following line from above:

 <xsl:copy-of select="document(unparsed-entity-uri(@detail))"/>
jscoot
@jscoot: That's nice!. However it is only possible, because your ENTITY is associated with an xml document. In the general case (non-XML document), the only way to read the data is by using the XSLT 2.0 function unparsed-text(). Glad I could be of help.
Dimitre Novatchev
A: 

unparsed-text (for non-XML document) function doesn't seem to be supported in IE8's XSLT. Is it possible to achieve the same effect using some other trick MSXML, JScript or something. I'm dependent on IE built in functions and no additional parser applicable

Tim