解决方案 »

  1.   


    第三个函数:
    int CMarkup::x_InsertNew( int iPosParent, int& iPosRel, NodePos& node )
    {
    // Parent empty tag or tags with no content?
    bool bEmptyParentTag = iPosParent && ELEM(iPosParent).IsEmptyElement();
    bool bNoContentParentTags = iPosParent && ! ELEM(iPosParent).ContentLen();
    if ( iPosRel && ! node.nLength ) // current position element?
    {
    node.nStart = ELEM(iPosRel).nStart;
    if ( ! (node.nNodeFlags & MNF_INSERT) ) // follow iPosRel
    node.nStart += ELEM(iPosRel).nLength;//*/////////////////////////////////////////////////////////////////////////////
    // Add by CLin 
    // 偏移换行符"\r\n", 在下面的"token.WhitespaceToTag( node.nStart )"处就不作偏移
    node.nStart += MCD_PSZLEN( x_EOL );
    //*/////////////////////////////////////////////////////////////////////////////
    }
    else if ( bEmptyParentTag ) // parent has no separate end tag?
    {
    // Split empty parent element
    if ( ELEM(iPosParent).nFlags & MNF_NONENDED )
    node.nStart = ELEM(iPosParent).StartContent();
    else
    node.nStart = ELEM(iPosParent).StartContent() - 1;
    }
    else if ( node.nLength || (m_nDocFlags&MDF_WRITEFILE) ) // non-element node or a file mode zero length position?
    {
    if ( ! (node.nNodeFlags & MNF_INSERT) )
    node.nStart += node.nLength; // after node or file mode position
    }
    else // no current node
    {
    // Insert relative to parent's content
    if ( node.nNodeFlags & (MNF_INSERT|MNF_REPLACE) )
    node.nStart = ELEM(iPosParent).StartContent(); // beginning of parent's content
    else // in front of parent's end tag
    node.nStart = ELEM(iPosParent).StartAfter() - ELEM(iPosParent).EndTagLen();
    } // Go up to start of next node, unless its splitting an empty element
    if ( ! (node.nNodeFlags&(MNF_WITHNOLINES|MNF_REPLACE)) && ! bEmptyParentTag )
    {
    TokenPos token( m_strDoc, m_nDocFlags );

    //*/////////////////////////////////////////////////////////////////////////
    // Modify by CLin
    // 当该元素拥有兄弟元素时, 不调整节点nStart(上面已经调整过)
    // 这里其实也是调整的作用, 但是如果在这里调整会跳过缩进的空格符 // node.nStart = token.WhitespaceToTag( node.nStart );
    if ( iPosRel != 0 && node.nNodeFlags != 16384 )
    node.nStart = token.WhitespaceToTag( node.nStart );
    //*//////////////////////////////////////////////////////////////////////////
    } // Is insert relative to element position? (i.e. not other kind of node)
    if ( ! node.nLength )
    {
    // Modify iPosRel to reflect position before
    if ( iPosRel )
    {
    if ( node.nNodeFlags & MNF_INSERT )
    {
    if ( ! (ELEM(iPosRel).nFlags & MNF_FIRST) )
    iPosRel = ELEM(iPosRel).iElemPrev;
    else
    iPosRel = 0;
    }
    }
    else if ( ! (node.nNodeFlags & MNF_INSERT) )
    {
    // If parent has a child, add after last child
    if ( ELEM(iPosParent).iElemChild )
    iPosRel = ELEM(ELEM(iPosParent).iElemChild).iElemPrev;
    }
    } // Get node length (needed for x_AddNode and x_AddSubDoc in file write mode)
    node.nLength = MCD_STRLENGTH(node.strMeta); // Prepare end of lines
    if ( (! (node.nNodeFlags & MNF_WITHNOLINES)) && (bEmptyParentTag || bNoContentParentTags) )
    node.nStart += x_EOLLEN;
    if ( ! (node.nNodeFlags & MNF_WITHNOLINES) )
    node.strMeta += x_EOL; // Calculate insert offset and replace length
    int nReplace = 0;
    int nInsertAt = node.nStart;
    if ( bEmptyParentTag )
    {
    MCD_STR strTagName = x_GetTagName( iPosParent );
    MCD_STR strFormat;
    if ( node.nNodeFlags & MNF_WITHNOLINES )
    strFormat = MCD_T(">");
    else
    strFormat = MCD_T(">") x_EOL;  strFormat += node.strMeta;//*//////////////////////////////////////////////////////////////////
    // Add by CLin
    // 添加子元素后, 会加上父元素的结束标签"</....."
    // 此处为父元素的结束标签增加了缩进
    int iLevel = x_GetNodeLevel( iPosParent );
    for (int iCount=0; iCount<iLevel; iCount++)
    strFormat += x_INDENT;
    //*///////////////////////////////////////////////////////////////////
    strFormat += MCD_T("</");
    strFormat += strTagName;
    node.strMeta = strFormat;
    if ( ELEM(iPosParent).nFlags & MNF_NONENDED )
    {
    nInsertAt = ELEM(iPosParent).StartAfter() - 1;
    nReplace = 0;
    ELEM(iPosParent).nFlags ^= MNF_NONENDED;
    }
    else
    {
    int i = m_strDoc.Find("<"+strTagName);
    nInsertAt = ELEM(iPosParent).StartAfter() - 2;
    nReplace = 1;
    ELEM(iPosParent).AdjustStartTagLen( -1 );
    }
    ELEM(iPosParent).SetEndTagLen( 3 + MCD_STRLENGTH(strTagName) );
    }
    else
    {
    if ( node.nNodeFlags & MNF_REPLACE )
    {
    nInsertAt = ELEM(iPosParent).StartContent();
    nReplace = ELEM(iPosParent).ContentLen();
    }
    else if ( bNoContentParentTags )
    {
    node.strMeta = x_EOL + node.strMeta;
    nInsertAt = ELEM(iPosParent).StartContent();
    }
    }
    if ( m_nDocFlags & MDF_WRITEFILE )
    {
    // Check if buffer is full
    int nNewDocLength = MCD_STRLENGTH(m_strDoc) + MCD_STRLENGTH(node.strMeta) - nReplace;
    int nFlushTo = node.nStart;
    MCD_STRCLEAR( m_strResult );
    if ( bEmptyParentTag )
    nFlushTo = ELEM(iPosParent).nStart;
    if ( nFlushTo && nNewDocLength > m_pFilePos->m_nBlockSizeBasis )
    {
    int nDocCapacity = MCD_STRCAPACITY(m_strDoc);
    if ( nNewDocLength > nDocCapacity )
    {
    if ( bEmptyParentTag )
    ELEM(iPosParent).nStart = 0;
    node.nStart -= nFlushTo;
    nInsertAt -= nFlushTo;
    m_pFilePos->FileFlush( m_strDoc, nFlushTo );
    m_strResult = m_pFilePos->m_strIOResult;
    }
    }
    } x_DocChange( nInsertAt, nReplace, node.strMeta );
    return nReplace;
    }
      

  2.   


    第二段代码好像显示的有点问题,,重新贴下MCD_STR CMarkup::x_GetTagName( int iPos ) const
    {
    // Return the tag name at specified element
    TokenPos token( m_strDoc, m_nDocFlags );
    token.m_nNext = ELEM(iPos).nStart + 1;//*////////////////////////////////////////////////////////////////////////
    // Add by CLin
    // 因为在元素起始标签加入了缩进, 在获取元素名的时候可能会获取错误, 返回"<"
    // 此处加入一个偏移, 获取元素名的时候偏移掉缩进量, 防止上述问题
    while ( token.m_pDocText[token.m_nNext - 1 ] != '<' )
    token.m_nNext ++;
    //*//////////////////////////////////////////////////////////////////////// if ( ! iPos || ! token.FindName() )
    return MCD_T(""); // Return substring of document
    return token.GetTokenText();
    }
    bool CMarkup::x_AddElem( MCD_PCSZ pName, MCD_PCSZ pValue, int nFlags )
    {
    if ( m_nDocFlags & MDF_READFILE )
    return false;
    if ( nFlags & MNF_CHILD )
    {
    // Adding a child element under main position
    if ( ! m_iPos || (m_nDocFlags & MDF_WRITEFILE) )
    return false;
    } // Cannot have data in non-ended element
    if ( (nFlags&MNF_WITHNOEND) && pValue && pValue[0] )
    return false; // Node and element structures
    NodePos node( nFlags );
    int iPosParent = 0, iPosBefore = 0;
    int iPos = x_GetFreePos();
    ElemPos* pElem = &ELEM(iPos); // Locate where to add element relative to current node
    if ( nFlags & MNF_CHILD )
    {
    iPosParent = m_iPos;
    iPosBefore = m_iPosChild;
    }
    else
    {
    iPosParent = m_iPosParent;
    iPosBefore = m_iPos;
    node.nStart = m_nNodeOffset;
    node.nLength = m_nNodeLength;
    } // Create string for insert
    // If no pValue is specified, an empty element is created
    // i.e. either <NAME>value</NAME> or <NAME/>
    ////*///////////////////////////////////////////////////////////////////
    // Add by CLin 2013/10/10
    // 添加元素时根据元素的节点等级确定缩进量 MCD_STR strBeginTag;
    int iLevel;
    int iIndentLen; strBeginTag.Format("<");
    iLevel = 0;
    iIndentLen = 0;

    if ( !(iPosParent == 0 && iPosBefore == 0) )
    {
    strBeginTag.Empty();
    iLevel = x_GetNodeLevel( iPosParent );

    for (int iCount=0; iCount<iLevel+1; iCount++)
    strBeginTag += x_INDENT; iIndentLen = strBeginTag.GetLength();
    strBeginTag += "<";
    }
    //*///////////////////////////////////////////////////////////////////// int nLenName = MCD_PSZLEN(pName);
    if ( ! pValue || ! pValue[0] )
    {
    // <NAME/> empty element

    //*///////////////////////////////////////////////////////////////////
    // Modify by CLin 2013/10/10
    // 根据不同缩进量分配内存
    // 并加上尖括号 // MCD_BLDRESERVE( node.strMeta, nLenName + 4 );
    // MCD_BLDAPPEND1( node.strMeta, '<' );
    // MCD_BLDAPPENDN( node.strMeta, pName, nLenName );
    MCD_BLDRESERVE( node.strMeta, nLenName + 4 + iIndentLen);
    MCD_BLDAPPENDN( node.strMeta, strBeginTag, iIndentLen + 1 );
    MCD_BLDAPPENDN( node.strMeta, pName, nLenName );
    //*/////////////////////////////////////////////////////////////////// if ( nFlags & MNF_WITHNOEND )
    {
    MCD_BLDAPPEND1( node.strMeta, '>' );
    }
    else
    {
    if ( nFlags & MNF_WITHXHTMLSPACE )
    {
    MCD_BLDAPPENDN( node.strMeta, MCD_T(" />"), 3 );
    }
    else
    {
    MCD_BLDAPPENDN( node.strMeta, MCD_T("/>"), 2 );
    }
    }
    MCD_BLDRELEASE( node.strMeta );
    pElem->nLength = MCD_STRLENGTH( node.strMeta );
    pElem->SetStartTagLen( pElem->nLength );
    pElem->SetEndTagLen( 0 );
    }
    else
    {
    // <NAME>value</NAME>
    MCD_STR strValue;
    if ( nFlags & MNF_WITHCDATA )
    strValue = x_EncodeCDATASection( pValue );
    else
    strValue = EscapeText( pValue, nFlags );
    int nLenValue = MCD_STRLENGTH(strValue);//*///////////////////////////////////////////////////////////////////
    // Modify by CLin
    // 根据不同缩进量分配内存
    // 并加上尖括号 // pElem->nLength = nLenName * 2 + nLenValue + 5;
    // MCD_BLDRESERVE( node.strMeta, pElem->nLength );
    // MCD_BLDAPPEND1( node.strMeta, '<' );
    // MCD_BLDAPPENDN( node.strMeta, pName, nLenName );
    pElem->nLength = nLenName * 2 + nLenValue + 5 + iIndentLen;
    MCD_BLDRESERVE( node.strMeta, pElem->nLength );
    MCD_BLDAPPENDN( node.strMeta, strBeginTag, iIndentLen + 1 );
    MCD_BLDAPPENDN( node.strMeta, pName, nLenName );
    //*///////////////////////////////////////////////////////////////////

    MCD_BLDAPPEND1( node.strMeta, '>' );
    MCD_BLDAPPENDN( node.strMeta, MCD_2PCSZ(strValue), nLenValue );
    MCD_BLDAPPENDN( node.strMeta, MCD_T("</"), 2 );
    MCD_BLDAPPENDN( node.strMeta, pName, nLenName );
    MCD_BLDAPPEND1( node.strMeta, '>' );
    MCD_BLDRELEASE( node.strMeta );
    pElem->SetEndTagLen( nLenName + 3 );
    pElem->SetStartTagLen( nLenName + 2 );
    } // Insert
    int nReplace = x_InsertNew( iPosParent, iPosBefore, node );
    pElem->nStart = node.nStart;
    pElem->iElemChild = 0;
    if ( nFlags & MNF_WITHNOEND )
    pElem->nFlags = MNF_NONENDED;
    else
    pElem->nFlags = 0;
    if ( m_nDocFlags & MDF_WRITEFILE )
    {
    iPosParent = x_UnlinkPrevElem( iPosParent, iPosBefore, iPos );
    TokenPos token( m_strDoc, m_nDocFlags );
    token.m_nL = pElem->nStart + 1;
    token.m_nR = pElem->nStart + nLenName;
    m_pFilePos->m_elemstack.PushTagAndCount( token );
    }
    else
    {
    x_LinkElem( iPosParent, iPosBefore, iPos );
    x_Adjust( iPos, MCD_STRLENGTH(node.strMeta) - nReplace );
    }
    if ( nFlags & MNF_CHILD )
    x_SetPos( m_iPosParent, iPosParent, iPos );
    else
    x_SetPos( iPosParent, iPos, 0 );
    return true;
    }
      

  3.   

    这个似乎太麻烦,我当初是自己解析中括号,然后自定义缩进,每遇到<>增加一个缩进级别,每遇到</>减少一个缩进级别。
      

  4.   

    其实我这边理论也是这样的
      只是因为是基于CMarkup来修改
    如果直接等它Save之后再处理的话就需要考虑到文件会越来越大的问题,会严重影响效率
     而如果希望在每次添加元素的时候进行处理
    就需要更新其中的某些成员变量,所以看起来比较麻烦,但是不会影响效率