bruno       2003/07/04 02:42:31

  Added:       src/webapp/samples/xinclude/content includehtml.xml
                        somehtml.xhtml
               src/java/org/apache/cocoon/components/xpointer
                        ElementPathPart.java
  Log:
  initial commit
  
  Revision  Changes    Path
  1.1                  cocoon-2.1/src/webapp/samples/xinclude/content/includehtml.xml
  
  Index: includehtml.xml
  ===================================================================
  <?xml version="1.0"?>
  <page xmlns:xi="http://www.w3.org/2001/XInclude";>
    <title>XInclude demo</title>
    <content>
      <para>This sample will include the content of the /html/body tag of the
        file somehtml.xhtml. This is done using the custom 'elementpath' XPointer
        scheme, which avoids building a DOM (which the xpointer() scheme does).</para>
      
<para><b><![CDATA[somehtml.xhtml#xmlns(c=http://apache.org/cocoon/xpointer)c:elementpath(/html/body)]]></b></para>
      <xi:include 
href="somehtml.xhtml#xmlns(c=http://apache.org/cocoon/xpointer)c:elementpath(/html/body)"/>
    </content>
  </page>
  
  
  
  1.1                  cocoon-2.1/src/webapp/samples/xinclude/content/somehtml.xhtml
  
  Index: somehtml.xhtml
  ===================================================================
  <html>
    <head>
      <title></title>
    </head>
    <body>
      <p>Hello, this is the content of the <tt>somehtml.xhtml</tt> file.</p>
      <p>And here's yet another paragraph from that file.</p>
    </body>
  </html>
  
  
  
  1.1                  
cocoon-2.1/src/java/org/apache/cocoon/components/xpointer/ElementPathPart.java
  
  Index: ElementPathPart.java
  ===================================================================
  package org.apache.cocoon.components.xpointer;
  
  import org.xml.sax.SAXException;
  import org.xml.sax.Attributes;
  import org.xml.sax.Locator;
  import org.apache.cocoon.xml.AbstractXMLPipe;
  import org.apache.cocoon.components.source.SourceUtil;
  import org.apache.cocoon.ProcessingException;
  
  import java.util.StringTokenizer;
  import java.util.ArrayList;
  import java.io.IOException;
  
  /**
   * A custom XPointer scheme that allows to include the content of a specific element 
without
   * building a DOM. The element must be specified using an absolute path reference 
such as
   * <tt>/html/body</tt>. Namespace prefixes within these element names are supported.
   *
   * <p>This xpointer scheme will always be succesful (thus any further xpointer parts 
will
   * never be executed).
   *
   * <p>The scheme name for this XPointer scheme is 'elementpath' and its namespace is
   * http://apache.org/cocoon/xpointer.
   *
   * <p>See the samples for a usage example.
   */
  public class ElementPathPart implements PointerPart {
      private String expression;
  
      public ElementPathPart(String expression) {
          this.expression = expression;
      }
  
      public boolean process(XPointerContext xpointerContext) throws SAXException {
          PathInclusionPipe pipe = new PathInclusionPipe(expression, xpointerContext);
          pipe.setConsumer(xpointerContext.getXmlConsumer());
          try {
              SourceUtil.toSAX(xpointerContext.getSource(), pipe);
          } catch (IOException e) {
              throw new SAXException("Exception while trying to XInclude data: " + 
e.getMessage(), e);
          } catch (ProcessingException e) {
              throw new SAXException("Exception while trying to XInclude data: " + 
e.getMessage(), e);
          }
          return true;
      }
  
      public static class PathInclusionPipe extends AbstractXMLPipe {
          /** The QNames that must be matched before inclusion can start. */
          private QName[] elementPath;
          /** The current element nesting level. */
          private int level;
          /** Should we currently be including? */
          private boolean include;
          /** The element nesting level since we started inclusion, used to know when 
to stop inclusion. */
          private int includeLevel;
  
          /** The element nesting level that should currently be matched. */
          private int levelToMatch;
          private boolean done;
  
          public PathInclusionPipe(String expression, XPointerContext xpointerContext) 
throws SAXException {
              // parse the expression to an array of QName objects
              ArrayList path = new ArrayList();
              StringTokenizer tokenizer = new StringTokenizer(expression, "/");
              while (tokenizer.hasMoreTokens()) {
                  String token = tokenizer.nextToken();
                  try {
                      path.add(QName.parse(token, xpointerContext));
                  } catch (SAXException e) {
                      throw new SAXException("Error in element path xpointer 
expression \"" + expression + "\": " + e.getMessage());
                  }
              }
              if (path.size() < 1)
                  throw new SAXException("Invalid element path xpointer expression \"" 
+ expression + "\".");
  
              this.elementPath = (QName[])path.toArray(new QName[0]);
              this.level = -1;
              this.include = false;
              this.levelToMatch = 0;
              this.done = false;
          }
  
          public void startElement(String namespaceURI, String localName, String raw, 
Attributes a)
                  throws SAXException {
              level++;
  
              if (include) {
                  super.startElement(namespaceURI, localName, raw, a);
                  return;
              }
  
              if (!done && level == levelToMatch && 
elementPath[level].matches(namespaceURI, localName)) {
                  levelToMatch++;
                  if (levelToMatch == elementPath.length) {
                      include = true;
                      done = true;
                      includeLevel = level;
                  }
              }
          }
  
          public void endElement(String uri, String loc, String raw)
                  throws SAXException {
              if (include && level == includeLevel)
                  include = false;
  
              if (include)
                  super.endElement(uri, loc, raw);
  
              level--;
          }
  
          public void setDocumentLocator(Locator locator) {
              if (include)
                  super.setDocumentLocator(locator);
          }
  
          public void startDocument()
                  throws SAXException {
              if (include)
                  super.startDocument();
          }
  
          public void endDocument()
                  throws SAXException {
              if (include)
                  super.endDocument();
          }
  
          public void startPrefixMapping(String prefix, String uri)
                  throws SAXException {
              // let namespace prefix alway through
              super.startPrefixMapping(prefix, uri);
          }
  
          public void endPrefixMapping(String prefix)
                  throws SAXException {
              // let namespace prefix alway through
              super.endPrefixMapping(prefix);
          }
  
          public void characters(char c[], int start, int len)
                  throws SAXException {
              if (include)
                  super.characters(c, start, len);
          }
  
          public void ignorableWhitespace(char c[], int start, int len)
                  throws SAXException {
              if (include)
                  super.ignorableWhitespace(c, start, len);
          }
  
          public void processingInstruction(String target, String data)
                  throws SAXException {
              if (include)
                  super.processingInstruction(target, data);
          }
  
          public void skippedEntity(String name)
                  throws SAXException {
              if (include)
                  super.skippedEntity(name);
          }
  
          public void startDTD(String name, String publicId, String systemId)
                  throws SAXException {
              if (include)
                  super.startDTD(name, publicId, systemId);
          }
  
          public void endDTD()
                  throws SAXException {
              if (include)
                  super.endDTD();
          }
  
          public void startEntity(String name)
                  throws SAXException {
              if (include)
                  super.startEntity(name);
          }
  
          public void endEntity(String name)
                  throws SAXException {
              if (include)
                  super.endEntity(name);
          }
  
          public void startCDATA()
                  throws SAXException {
              if (include)
                  super.startCDATA();
          }
  
          public void endCDATA()
                  throws SAXException {
              if (include)
                  super.endCDATA();
          }
  
          public void comment(char ch[], int start, int len)
                  throws SAXException {
              if (include)
                  super.comment(ch, start, len);
          }
  
          public static class QName {
              private String namespaceURI;
              private String localName;
  
              public QName(String namespaceURI, String localName) {
                  this.namespaceURI = namespaceURI;
                  this.localName = localName;
              }
  
              public static QName parse(String qName, XPointerContext xpointerContext) 
throws SAXException {
                  int pos = qName.indexOf(':');
                  if (pos > 0) {
                      String prefix = qName.substring(0, pos);
                      String localName = qName.substring(pos + 1);
                      String namespaceURI = xpointerContext.prefixToNamespace(prefix);
                      if (namespaceURI == null)
                          throw new SAXException("Namespace prefix \"" + prefix + "\" 
not declared.");
                      return new QName(prefix, localName);
                  }
                  return new QName("", qName);
              }
  
              public String getNamespaceURI() {
                  return namespaceURI;
              }
  
              public String getLocalName() {
                  return localName;
              }
  
              public boolean matches(String namespaceURI, String localName) {
                  return this.localName.equals(localName) && 
this.namespaceURI.equals(namespaceURI);
              }
          }
      }
  }
  
  
  

Reply via email to