text: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the  "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  #include "ElemPI.hpp"
  
  
  
  #include <xercesc/sax/AttributeList.hpp>
  
  
  
  #include <xalanc/PlatformSupport/DOMStringHelper.hpp>
  #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
  
  
  
  #include "AVT.hpp"
  #include "Constants.hpp"
  #include "StylesheetConstructionContext.hpp"
  #include "StylesheetExecutionContext.hpp"
  
  
  
  namespace XALAN_CPP_NAMESPACE {
  
  
  
  ElemPI::ElemPI(
              StylesheetConstructionContext&  constructionContext,
              Stylesheet&                     stylesheetTree,
              const AttributeListType&        atts,
              XalanFileLoc                    lineNumber, 
              XalanFileLoc                    columnNumber) :
      ElemTemplateElement(
          constructionContext,
          stylesheetTree,
          lineNumber,
          columnNumber,
          StylesheetConstructionContext::ELEMNAME_PI),
      m_nameAVT(0)
  {
      const XalanSize_t  nAttrs = atts.getLength();
  
      for(XalanSize_t i = 0; i < nAttrs; i++)
      {
          const XalanDOMChar* const   aname = atts.getName(i);
  
          if (equals(aname, Constants::ATTRNAME_NAME))
          {           
              m_nameAVT =
                      constructionContext.createAVT(getLocator(), aname, atts.getValue(i), *this);
          }
          else if (isAttrOK(
                      aname,
                      atts,
                      i,
                      constructionContext) == false &&
                   processSpaceAttr(
                      Constants::ELEMNAME_PI_WITH_PREFIX_STRING.c_str(),
                      aname,
                      atts,
                      i,
                      constructionContext) == false)
          {
              error(
                  constructionContext,
                  XalanMessages::ElementHasIllegalAttribute_2Param,
                  Constants::ELEMNAME_PI_WITH_PREFIX_STRING.c_str(),
                  aname);
          }
      }
  
      if (0 == m_nameAVT)
      {
          error(
              constructionContext,
              XalanMessages::ElementMustHaveAttribute_2Param,
              Constants::ELEMNAME_PI_WITH_PREFIX_STRING,
              Constants::ATTRNAME_NAME);
      }
  }
  
  
  
  ElemPI::~ElemPI()
  {
  }
  
  
  
  const XalanDOMString&
  ElemPI::getElementName() const
  {
      return Constants::ELEMNAME_PI_WITH_PREFIX_STRING;
  }
  
  
  
  #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
  const ElemTemplateElement*
  ElemPI::startElement(StylesheetExecutionContext&    executionContext) const
  {
      ElemTemplateElement::startElement(executionContext);
      
      XalanDOMString& piName = executionContext.getAndPushCachedString();
  
      m_nameAVT->evaluate(piName, *this, executionContext);
  
      if (equalsIgnoreCaseASCII(
              piName,
              Constants::ATTRVAL_OUTPUT_METHOD_XML) ||
         isValidNCName(piName) == false)
      {
          error(
              executionContext,
              XalanMessages::PINameInvalid_1Param,
              piName);
      }
  
      XalanDOMString& theResult = executionContext.getAndPushCachedString();
  
      executionContext.pushCopyTextNodesOnly(true);
  
      return beginChildrenToString(executionContext,theResult);
  }
  
  
  
  void
  ElemPI::endElement(StylesheetExecutionContext&  executionContext) const
  {
      endChildrenToString(executionContext);
  
      XalanDOMString&     piData =
          executionContext.getAndPopCachedString();
  
      const XalanDOMString&   piName =
          executionContext.getAndPopCachedString();
  
      XalanDOMString::iterator    theEnd =
          piData.end();
  
      XalanDOMString::iterator    theCurrent =
          piData.begin();
  
      // We need to fix up any occurrences of the sequence '?>' in
      // the PI's data by inserting a space between them.
      while (theCurrent != theEnd)
      {
          const XalanDOMChar  theChar = *theCurrent;
  
          if (theChar == XalanUnicode::charQuestionMark)
          {
              XalanDOMString::iterator    theNext =
                  theCurrent + 1;
  
              if (theNext != theEnd &&
                  *theNext == XalanUnicode::charGreaterThanSign)
              {
                  theCurrent =
                      piData.insert(
                          theNext,
                          XalanUnicode::charSpace);
  
                  theEnd = piData.end();
  
                  // Move forward, since we're not interested in
                  // the '>' character.
                  ++theCurrent;
              }
          }
  
          ++theCurrent;
      }
  
      executionContext.processingInstruction(
                  piName.c_str(),
                  piData.c_str());
  
      executionContext.popCopyTextNodesOnly();
  }
  #endif
  
  
  
  #if defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
  void
  ElemPI::execute(StylesheetExecutionContext&     executionContext) const
  {
      ElemTemplateElement::execute(executionContext);
      
      const StylesheetExecutionContext::GetCachedString   theGuard(executionContext);
  
      XalanDOMString&     piName = theGuard.get();
  
      m_nameAVT->evaluate(piName, *this, executionContext);
  
      if (equalsIgnoreCaseASCII(
              piName,
              Constants::ATTRVAL_OUTPUT_METHOD_XML) ||
         isValidNCName(piName) == false)
      {
          error(
              executionContext,
              XalanMessages::PINameInvalid_1Param,
              piName);
      }
  
      StylesheetExecutionContext::SetAndRestoreCopyTextNodesOnly  theSetAndRestore(executionContext, true);
  
      childrenToResultPI(
              executionContext,
              piName);
  }
  #endif
  
  
  
  bool
  ElemPI::childTypeAllowed(int    xslToken) const
  {
      bool    fResult = false;
      
      switch(xslToken)
      {
      // char-instructions 
      case StylesheetConstructionContext::ELEMNAME_TEXT_LITERAL_RESULT:
      case StylesheetConstructionContext::ELEMNAME_APPLY_TEMPLATES:
      case StylesheetConstructionContext::ELEMNAME_APPLY_IMPORTS:
      case StylesheetConstructionContext::ELEMNAME_CALL_TEMPLATE:
      case StylesheetConstructionContext::ELEMNAME_FOR_EACH:
      case StylesheetConstructionContext::ELEMNAME_VALUE_OF:
      case StylesheetConstructionContext::ELEMNAME_COPY_OF:
      case StylesheetConstructionContext::ELEMNAME_NUMBER:
      case StylesheetConstructionContext::ELEMNAME_CHOOSE:
      case StylesheetConstructionContext::ELEMNAME_IF:
      case StylesheetConstructionContext::ELEMNAME_TEXT:
      case StylesheetConstructionContext::ELEMNAME_COPY:
      case StylesheetConstructionContext::ELEMNAME_VARIABLE:
      case StylesheetConstructionContext::ELEMNAME_MESSAGE:
          fResult = true;
          break;
          
      default:
          break;
      }
      
      return fResult;
  }
  
  
  
  }
  