解决方案 »

  1.   

    我是使用ue或者notepad++查看到 ,不论有没有换行缩进都会自动按规则显示。
      

  2.   

    哈哈,楼主 
      我正好前一段时间也在搞这个,当时也在纠结缩进的问题,据说CMarkup的收费版是有缩进功能的
    有一个Format函数,但是毕竟收费呢不是。
     最早我写了个递归函数来处理,因为CMarkup处理XML的时候  在内存中的m_strDoc变量保存了整个文档的数据(不管你是新建的还是load进来的),在保存的时候(Save()函数)写入文件,于是我就添加了一个SaveAndFormat函数,每次都将当前元素的子元素递归处理,不过处理效率不好,当XML文档越来越大的时候就会越来越慢。
       这两天又想起这个来,想着既然人家有那么方便的函数来添加元素、属性等,直接在添加的时候把缩进字符加入就可以了,不过要考虑到元素长度的变化等内容,但是最终还是实现了。
     下面给你代码:// 在Markup.h 头文件中添加如下定义
    //*///////////////////////////////////////////////////////////////////
    // Add by CLin
    // 定义缩进标识符(此处为2个空格符, 也可以使用制表符\t)
    #define x_INDENT MCD_T("  ") // can be \t or empty
    //*/////////////////////////////////////////////////////////////////////*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 保存并格式化函数
    bool SaveAndFormat( MCD_CSTR_FILENAME szFileName );
    //*/////////////////////////////////////////////////////////////////*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 格式化函数以及节点分级函数
    bool x_FormatDoc( MCD_STR &strDoc, UINT iLevel );
    int  x_GetNodeLevel( int iNodePos );
    //*////////////////////////////////////////////////////////////////////////////-------------分割线-------------////////////////////////Markup.cpp 文件中添加如下函数实现
    //*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 格式化文档函数(使用递归, 当文档变大时, 效率低下)
    bool CMarkup::x_FormatDoc( MCD_STR &strDoc, UINT iLevel )
    {
    if ( MCD_STRISEMPTY( strDoc) )
    return true; MCD_STR strSepaDoc;
    MCD_STR strFormatted;
    MCD_STR strRow;
    MCD_STR strItem;
    MCD_STR strIndent; strSepaDoc = strDoc;
    strFormatted.Empty();
    strRow.Empty();
    strItem.Empty();
    strIndent.Empty(); // 根据节点等级计算缩进量
    for (int iInd=0;iInd<(int)iLevel; iInd++)
    strIndent += x_INDENT; // 缩进
    for (int iTemp=0; iTemp<MCD_STRLENGTH(strSepaDoc); iTemp++)
    {
    // 截取到一行
    if (strSepaDoc[iTemp] != '\r' && strSepaDoc[iTemp+1] != '\n')
    continue; strRow = strSepaDoc.Left(iTemp + 2);
    strSepaDoc = strSepaDoc.Mid(iTemp + 2); // 获取元素名
    sscanf(strRow, "<%s>", strItem.GetBuffer(128));
    strItem.ReleaseBuffer();
    if (strItem.Find(">") != -1)
    strItem = strItem.Left(strItem.Find(">")); // 如果该行已经格式化则不做处理
    if (strRow.Find("<") > 0)
    strFormatted += strRow;
    else
    strFormatted += strIndent + strRow; // 该元素无子元素
    if (strRow.Find("</") != -1 || strRow.Find("/>") != -1)
    {
    iTemp = 0;
    continue;
    } // 该元素有子元素, 则截取子元素集合递归处理
    iTemp = strSepaDoc.Find("</" + strItem + ">");
    strRow = strSepaDoc.Left(iTemp);
    strSepaDoc = strSepaDoc.Mid(iTemp);
    x_FormatDoc(strRow, iLevel+1); strFormatted += strRow;
    iTemp = 0;
    continue;
    } strDoc = strFormatted;
    return true;
    }int  CMarkup::x_GetNodeLevel( int iNodePos )
    {
    if ( iNodePos <= 0)
    return -1; if ( iNodePos == 1 )
    return 0; int iLevel;
    iLevel = 0; while ( iNodePos != 1 )
    {
    iNodePos = x_GetParent( iNodePos );
    iLevel++;
    } return iLevel;
    }
    //*/////////////////////////////////////////////////////////////////*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 保存并格式化函数
    bool CMarkup::SaveAndFormat( MCD_CSTR_FILENAME szFileName )
    {
    if ( m_nDocFlags & (MDF_READFILE|MDF_WRITEFILE) )
    return false; MCD_STR strFormattedDoc;
    MCD_STR strDocHeader;
    MCD_STR strDocBody; strFormattedDoc = m_strDoc;
    strDocHeader = strFormattedDoc.Left( strFormattedDoc.Find("?>") + 4 );
    strDocBody = strFormattedDoc.Mid( strFormattedDoc.Find("?>") + 4);
    if ( ! x_FormatDoc( strDocBody, 0 ) )
    return false; strFormattedDoc = strDocHeader + strDocBody; return WriteTextFile( szFileName, strFormattedDoc, &m_strResult, &m_nDocFlags );
    }
    //*///////////////////////////////////////////////////////////////
      

  3.   

    哈哈,楼主 
      我正好前一段时间也在搞这个,当时也在纠结缩进的问题,据说CMarkup的收费版是有缩进功能的
    有一个Format函数,但是毕竟收费呢不是。
     最早我写了个递归函数来处理,因为CMarkup处理XML的时候  在内存中的m_strDoc变量保存了整个文档的数据(不管你是新建的还是load进来的),在保存的时候(Save()函数)写入文件,于是我就添加了一个SaveAndFormat函数,每次都将当前元素的子元素递归处理,不过处理效率不好,当XML文档越来越大的时候就会越来越慢。
       这两天又想起这个来,想着既然人家有那么方便的函数来添加元素、属性等,直接在添加的时候把缩进字符加入就可以了,不过要考虑到元素长度的变化等内容,但是最终还是实现了。
     下面给你代码:// 在Markup.h 头文件中添加如下定义
    //*///////////////////////////////////////////////////////////////////
    // Add by CLin
    // 定义缩进标识符(此处为2个空格符, 也可以使用制表符\t)
    #define x_INDENT MCD_T("  ") // can be \t or empty
    //*/////////////////////////////////////////////////////////////////////*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 保存并格式化函数
    bool SaveAndFormat( MCD_CSTR_FILENAME szFileName );
    //*/////////////////////////////////////////////////////////////////*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 格式化函数以及节点分级函数
    bool x_FormatDoc( MCD_STR &strDoc, UINT iLevel );
    int  x_GetNodeLevel( int iNodePos );
    //*////////////////////////////////////////////////////////////////////////////-------------分割线-------------////////////////////////Markup.cpp 文件中添加如下函数实现
    //*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 格式化文档函数(使用递归, 当文档变大时, 效率低下)
    bool CMarkup::x_FormatDoc( MCD_STR &strDoc, UINT iLevel )
    {
    if ( MCD_STRISEMPTY( strDoc) )
    return true; MCD_STR strSepaDoc;
    MCD_STR strFormatted;
    MCD_STR strRow;
    MCD_STR strItem;
    MCD_STR strIndent; strSepaDoc = strDoc;
    strFormatted.Empty();
    strRow.Empty();
    strItem.Empty();
    strIndent.Empty(); // 根据节点等级计算缩进量
    for (int iInd=0;iInd<(int)iLevel; iInd++)
    strIndent += x_INDENT; // 缩进
    for (int iTemp=0; iTemp<MCD_STRLENGTH(strSepaDoc); iTemp++)
    {
    // 截取到一行
    if (strSepaDoc[iTemp] != '\r' && strSepaDoc[iTemp+1] != '\n')
    continue; strRow = strSepaDoc.Left(iTemp + 2);
    strSepaDoc = strSepaDoc.Mid(iTemp + 2); // 获取元素名
    sscanf(strRow, "<%s>", strItem.GetBuffer(128));
    strItem.ReleaseBuffer();
    if (strItem.Find(">") != -1)
    strItem = strItem.Left(strItem.Find(">")); // 如果该行已经格式化则不做处理
    if (strRow.Find("<") > 0)
    strFormatted += strRow;
    else
    strFormatted += strIndent + strRow; // 该元素无子元素
    if (strRow.Find("</") != -1 || strRow.Find("/>") != -1)
    {
    iTemp = 0;
    continue;
    } // 该元素有子元素, 则截取子元素集合递归处理
    iTemp = strSepaDoc.Find("</" + strItem + ">");
    strRow = strSepaDoc.Left(iTemp);
    strSepaDoc = strSepaDoc.Mid(iTemp);
    x_FormatDoc(strRow, iLevel+1); strFormatted += strRow;
    iTemp = 0;
    continue;
    } strDoc = strFormatted;
    return true;
    }int  CMarkup::x_GetNodeLevel( int iNodePos )
    {
    if ( iNodePos <= 0)
    return -1; if ( iNodePos == 1 )
    return 0; int iLevel;
    iLevel = 0; while ( iNodePos != 1 )
    {
    iNodePos = x_GetParent( iNodePos );
    iLevel++;
    } return iLevel;
    }
    //*/////////////////////////////////////////////////////////////////*///////////////////////////////////////////////////////////////
    // Add by CLin (递归部分)
    // 保存并格式化函数
    bool CMarkup::SaveAndFormat( MCD_CSTR_FILENAME szFileName )
    {
    if ( m_nDocFlags & (MDF_READFILE|MDF_WRITEFILE) )
    return false; MCD_STR strFormattedDoc;
    MCD_STR strDocHeader;
    MCD_STR strDocBody; strFormattedDoc = m_strDoc;
    strDocHeader = strFormattedDoc.Left( strFormattedDoc.Find("?>") + 4 );
    strDocBody = strFormattedDoc.Mid( strFormattedDoc.Find("?>") + 4);
    if ( ! x_FormatDoc( strDocBody, 0 ) )
    return false; strFormattedDoc = strDocHeader + strDocBody; return WriteTextFile( szFileName, strFormattedDoc, &m_strResult, &m_nDocFlags );
    }
    //*///////////////////////////////////////////////////////////////
    以上内容已经将递归算法部分说明了
      如果考虑到你要处理的文档元素很多,那么可以考虑下面的,直接在AddItem的时候加入缩进字符
      

  4.   


    想要在添加元素的时候加入缩进量,只需要修改三个函数
    x_GetTagName
    x_AddElem
    x_InsertNew
    // 此函数作用是获取指定元素的元素名
    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();
    }// AddItem和AddChildItem函数都会调用该函数, 注意我添加或者修改的部分即可
    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;
    }