Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6206491

IDs disappear from documents after document() method is called.

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 6
    • 5.0
    • xml

      FULL PRODUCT VERSION :
      java version "1.5.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
      Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)


      ADDITIONAL OS VERSION INFORMATION :
      Linux 2.6.5 i686 unknown

      A DESCRIPTION OF THE PROBLEM :
      The problem ocurs only if one of the documents declares some namespace.

      Use two XML documents with some namespace declared in at least one
      of them. Load one xml document with the xsl document on the command
      line, and one with a call to document(). You can not refer to the
      IDs in either document.


      1.
      If we load another xml document with a document() call, any ID references held
      by the document we now have open will disappear.

      The problem is fixed if we also load the main document explicitly after the
      external stylesheet is loaded. The main document must be loaded by name;
      using an empty string will not work.

      -------------------------------------------------------------------------------

      2.
      IDs in a second document, loaded with a document() call, always disappear.
      In the test case, the id() call even finds a node in the wrong document, with
      a wrong id.

      -------------------------------------------------------------------------------

      This bug causes NullPointerException to be thrown in some stylesheets which
      use the id() method.

      The NullPointerException occurs in SAX2DTM2.java:1991
      method name: _type2
      Cause:
      m_exptype_map is null.
      Apparently it is null because it has not been initialized by a call to endDocument().



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run test app with:
      javac xsltest.java
      java xsltest test.xsl test.xml

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The result file, test1.html includes the output.
      The file should list the @count attribute for the elements.
      ACTUAL -
      The @count attribute is not found. Actually, the element is not found
      at all. Something is found, but what is unclear. At least in one case
      a random element from the wrong document is found.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // All 4 files are below.
      // I also posted them at http://www.tksoft.com/sun/
      // under "javabug4"
      // xsltest.java
      import java.io.File;
      import java.io.IOException;

      import javax.xml.transform.TransformerException;
      import javax.xml.transform.TransformerConfigurationException;
      import javax.xml.transform.Transformer;
      import javax.xml.transform.TransformerFactory;

      import javax.xml.transform.dom.DOMSource;

      import javax.xml.transform.stream.StreamSource;
      import javax.xml.transform.stream.StreamResult;

      import javax.xml.parsers.ParserConfigurationException;
      import javax.xml.parsers.DocumentBuilderFactory;
      import javax.xml.parsers.DocumentBuilder;

      import org.xml.sax.SAXException;
      import org.xml.sax.SAXParseException;

      import org.w3c.dom.Document;

      public class xsltest {

          static public void main (String[] argv) {
              if (argv.length != 2) {
                  System.err.println("Usage: xslfile xmlfile.");
                  System.exit(-1);
              }
              try {
                  File xmlFile = new File(argv[1]);
                  Document document = getNewXmlDoc(xmlFile);
                  xmlxsl2html(new File(argv[0]), document, new File("test1.html"));
              } catch (Exception ex) {
                  System.err.println(ex.getMessage());
                  ex.printStackTrace(System.err);
              }
              System.err.println("test1.html contains the output.");
          }

          static void xmlxsl2html(File xslFile, Document document, File targetfile) throws Exception {

              try {
                  TransformerFactory tFactory = TransformerFactory.newInstance();
                  StreamSource stylesource = new StreamSource(xslFile);
                  Transformer transformer = tFactory.newTransformer(stylesource);

                  transformer.clearParameters();

                  DOMSource source = new DOMSource(document);

                  StreamResult result = new StreamResult(targetfile);
                  transformer.transform(source, result);

              } catch (TransformerConfigurationException ex) {
                  throw ex;

              } catch (TransformerException ex) {
                  throw ex;
              }


          }

          static Document getNewXmlDoc(File xmlFile) throws Exception {

              DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
              factory.setNamespaceAware(true);
              factory.setValidating(true);

              try {
                  DocumentBuilder builder = factory.newDocumentBuilder();
                  builder.setErrorHandler(new org.xml.sax.helpers.DefaultHandler() {
                      public void fatalError(SAXParseException e) throws SAXParseException {
                          throw e;
                      }
                      public void error(SAXParseException e) throws SAXParseException {
                          throw e;
                      }
                      public void warning(SAXParseException e) throws SAXParseException {
                          throw e;
                      }
                  });
                  return builder.parse(xmlFile);

              } catch (SAXException ex) {
                  throw ex;
              } catch (ParserConfigurationException ex) {
                  throw ex;
              } catch (IOException ex) {
                  throw ex;
              }
          }


      }


      // test.xml

      <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>

      <!DOCTYPE organization [
          <!ELEMENT organization (company*,ids)>
          <!ELEMENT company (#PCDATA | department | equipment:instance)*>
          <!ELEMENT ids (id*)>
          <!ELEMENT id EMPTY>
          <!ELEMENT department EMPTY>
          <!ELEMENT equipment:instance EMPTY>

          <!ATTLIST organization id ID #IMPLIED
                                  xmlns:equipment CDATA #FIXED "http://namespaces.tksoft.com/equipment/"
          >
          <!ATTLIST company id ID #REQUIRED
                              count CDATA #REQUIRED
          >
          <!ATTLIST department id ID #REQUIRED
          >
          <!ATTLIST equipment:instance id ID #REQUIRED
          >
          <!ATTLIST id
              value IDREF #REQUIRED
          >
      ]>

      <organization>
          <company id="ca" count="2">
              <department id="da"/>
              <equipment:instance id="ea"/>
              <equipment:instance id="eb"/>
          </company>
          <company id="cb" count="0">
          </company>
          <company id="cc" count="5">
          </company>
          <ids>
              <id value="ca"/>
              <id value="cb"/>
          </ids>
      </organization>

      // test2.xml
      <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>

      <!DOCTYPE organization2 [
          <!ELEMENT organization2 (company*,ids)>
          <!ELEMENT company (#PCDATA | department)*>
          <!ELEMENT ids (id*)>
          <!ELEMENT id EMPTY>
          <!ELEMENT department EMPTY>
          
          <!ATTLIST organization id ID #IMPLIED
          >
          <!ATTLIST company id ID #REQUIRED
                              count CDATA #REQUIRED
          >
          <!ATTLIST department id ID #REQUIRED
          >
          <!ATTLIST id
              value IDREF #REQUIRED
          >
      ]>
          

      <organization2>
          <company id="xca" count="2">
              <department id="xda"/>
          </company>
          <company id="xcb" count="0">
          </company>
          <company id="xcc" count="5">
          </company>
          <ids>
              <id value="xca"/>
              <id value="xcb"/>
          </ids>
      </organization2>

      // test.xsl
      <?xml version="1.0" encoding="ISO-8859-1"?>

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                                      xmlns="http://www.w3.org/1999/xhtml"
                                      xmlns:equipment="http://namespaces.tksoft.com/equipment/"
      >
          
          
      <xsl:variable name="companies" select="//company"/>
      <xsl:variable name="ids" select="//ids//id"/>
      <xsl:variable name="dummy" select="document('test2.xml')"/>
      <!--
      Comment out this dummy2 line to make ids disappear from the main document as well.
      -->
      <xsl:variable name="dummy2" select="document('test.xml')"/>
          
          
      <xsl:template match="/">
      Test to make id maps disappear. Bug exists in jdk 5.0, not in j2se 1.4.
      The following ids disappear only if dummy2 is commented out:
      <xsl:apply-templates select="$ids"/>
      The following ids always disappear:
      <xsl:apply-templates select="$dummy//ids/id"/>
      <xsl:text>
      </xsl:text>
      </xsl:template>
          
          


      <xsl:template match="id">
              
          <!-- the context node is the id element. The @value attribute refers to an id
               in the same document, so it should be found. The rules for id() say that
               the ids which are searched are those in the document of the context node.
          -->
          <xsl:variable name="entity" select="id(@value)"/>

          Entity id: <xsl:value-of select="@value"/>,
          match count: <xsl:value-of select="count($entity)"/>,
          match tagname: <xsl:value-of select="name($entity)"/>,
          attrs: <xsl:value-of select="$entity/@*"/>,
          count attr: <xsl:value-of select="$entity/@count"/>

      </xsl:template>

      </xsl:stylesheet>


      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Don't load documents with document() if they contain IDs. Load such
      documents as the primary document. Load documents without IDs
      with document(), and lastly add a redundant call to document()
      to load the primary document.
      ###@###.### 2004-12-09 17:04:54 GMT

            spericas Santiago Pericasgeertsen
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: