MSXML من C++ - جميلة طباعة / indent المستندات التي تم إنشاؤها حديثا

StackOverflow https://stackoverflow.com/questions/164575

  •  03-07-2019
  •  | 
  •  

سؤال

أنا كتابة ملفات XML باستخدام محلل MSXML ، مع مجمع يمكنني تحميلها من هنا: http://www.codeproject.com/KB/XML/JW_CXml.aspx.يعمل كبيرة إلا أنه عند إنشاء مستند جديد من مدونة (حتى يتم تحميل من ملف تعديل) ، والنتيجة هي كل واحد في خط كبير.أود العناصر أن تكون بادئة بشكل جيد بحيث لا يمكن قراءتها بسهولة في محرر نص.

غوغلينغ يظهر كثير من الناس مع نفس السؤال - وردا على سؤال حول 2001 أو نحو ذلك.الردود عادة ما يقول 'تطبيق تحويل XSL' أو 'إضافة الخاصة بك بيضاء العقد'.خصوصا آخر واحد يجعلني أذهب %( لذلك أنا على أمل أنه في عام 2008 هناك طريقة أسهل إلى حد MSXML الانتاج.لذا سؤالي ؛ هناك, وكيف يمكنني استخدامه ؟

هل كانت مفيدة؟

المحلول

وجرب هذا، لقد وجدت هذا منذ سنوات على شبكة الإنترنت.

#include <msxml2.h>

bool FormatDOMDocument (IXMLDOMDocument *pDoc, IStream *pStream)
{

    // Create the writer

    CComPtr <IMXWriter> pMXWriter;
    if (FAILED (pMXWriter.CoCreateInstance(__uuidof (MXXMLWriter), NULL, CLSCTX_ALL)))
    {
        return false;
    }
    CComPtr <ISAXContentHandler> pISAXContentHandler;
    if (FAILED (pMXWriter.QueryInterface(&pISAXContentHandler)))
    {
        return false;
    }
    CComPtr <ISAXErrorHandler> pISAXErrorHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXErrorHandler)))
    {
        return false;
    }
    CComPtr <ISAXDTDHandler> pISAXDTDHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXDTDHandler)))
    {
        return false;
    }

    if (FAILED (pMXWriter ->put_omitXMLDeclaration (VARIANT_FALSE)) ||
        FAILED (pMXWriter ->put_standalone (VARIANT_TRUE)) ||
        FAILED (pMXWriter ->put_indent (VARIANT_TRUE)) ||
        FAILED (pMXWriter ->put_encoding (L"UTF-8")))
    {
        return false;
    }

    // Create the SAX reader

    CComPtr <ISAXXMLReader> pSAXReader;
    if (FAILED (pSAXReader.CoCreateInstance (__uuidof (SAXXMLReader), NULL, CLSCTX_ALL)))
    {
        return false;
    }

    if (FAILED (pSAXReader ->putContentHandler (pISAXContentHandler)) ||
        FAILED (pSAXReader ->putDTDHandler (pISAXDTDHandler)) ||
        FAILED (pSAXReader ->putErrorHandler (pISAXErrorHandler)) ||
        FAILED (pSAXReader ->putProperty (
        L"http://xml.org/sax/properties/lexical-handler", CComVariant (pMXWriter))) ||
        FAILED (pSAXReader ->putProperty (
        L"http://xml.org/sax/properties/declaration-handler", CComVariant (pMXWriter))))
    {
        return false;
    }

    // Perform the write

    return 
       SUCCEEDED (pMXWriter ->put_output (CComVariant (pStream))) &&
       SUCCEEDED (pSAXReader ->parse (CComVariant (pDoc)));
}

نصائح أخرى

وهنا نسخة معدلة من الإجابة مقبولة من شأنها أن تحول في الذاكرة (التغييرات فقط في الأسطر القليلة الماضية ولكن أنا نشر كتلة كله من أجل راحة قراء المستقبل):

bool CXml::FormatDOMDocument(IXMLDOMDocument *pDoc)
{
    // Create the writer
    CComPtr <IMXWriter> pMXWriter;
    if (FAILED (pMXWriter.CoCreateInstance(__uuidof (MXXMLWriter), NULL, CLSCTX_ALL))) {
        return false;
    }
    CComPtr <ISAXContentHandler> pISAXContentHandler;
    if (FAILED (pMXWriter.QueryInterface(&pISAXContentHandler))) {
        return false;
    }
    CComPtr <ISAXErrorHandler> pISAXErrorHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXErrorHandler))) {
        return false;
    }
    CComPtr <ISAXDTDHandler> pISAXDTDHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXDTDHandler))) {
        return false;
    }

    if (FAILED (pMXWriter->put_omitXMLDeclaration (VARIANT_FALSE)) ||
        FAILED (pMXWriter->put_standalone (VARIANT_TRUE)) ||
        FAILED (pMXWriter->put_indent (VARIANT_TRUE)) ||
        FAILED (pMXWriter->put_encoding (L"UTF-8")))
    {
        return false;
    }

    // Create the SAX reader
    CComPtr <ISAXXMLReader> pSAXReader;
    if (FAILED(pSAXReader.CoCreateInstance(__uuidof (SAXXMLReader), NULL, CLSCTX_ALL))) {
        return false;
    }

    if (FAILED(pSAXReader->putContentHandler (pISAXContentHandler)) ||
        FAILED(pSAXReader->putDTDHandler (pISAXDTDHandler)) ||
        FAILED(pSAXReader->putErrorHandler (pISAXErrorHandler)) ||
        FAILED(pSAXReader->putProperty (L"http://xml.org/sax/properties/lexical-handler", CComVariant (pMXWriter))) ||
        FAILED(pSAXReader->putProperty (L"http://xml.org/sax/properties/declaration-handler", CComVariant (pMXWriter))))
    {
        return false;
    }

    // Perform the write
    bool success1 = SUCCEEDED(pMXWriter->put_output(CComVariant(pDoc.GetInterfacePtr())));
    bool success2 = SUCCEEDED(pSAXReader->parse(CComVariant(pDoc.GetInterfacePtr())));

    return success1 && success2;
}

حتى 2 سنت تصل 7 سنوات في وقت لاحق أعتقد أن السؤال لا يزال يستحق إجابة بسيطة ملفوفة في فقط بضعة أسطر من التعليمات البرمجية التي من الممكن باستخدام Visual C++'s #import التوجيه و الأم C++ COM دعم مكتبة (تقدم المؤشرات الذكية و تغليف معالجة الخطأ).

علما بأن مثل قبول الإجابة عليه لا تحاول أن تنسجم CXml الفئة المهمة باستخدام وإنما يدل على جوهر الفكرة.كما أفترض msxml6.

جميلة الطباعة إلى أي تيار

void PrettyWriteXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, IStream* stream)
{
    MSXML2::IMXWriterPtr writer(__uuidof(MSXML2::MXXMLWriter60));
    writer->encoding = L"utf-8";
    writer->indent = _variant_t(true);
    writer->standalone = _variant_t(true);
    writer->output = stream;

    MSXML2::ISAXXMLReaderPtr saxReader(__uuidof(MSXML2::SAXXMLReader60));
    saxReader->putContentHandler(MSXML2::ISAXContentHandlerPtr(writer));
    saxReader->putProperty(PUSHORT(L"http://xml.org/sax/properties/lexical-handler"), writer.GetInterfacePtr());
    saxReader->parse(xmlDoc);
}

تيار الملف

إذا كنت في حاجة الى تيار الكتابة إلى ملف تحتاج إلى تنفيذ IStream واجهة.
wtlext وقد حصلت على الدرجة التي يمكنك استخدامها أو التي يمكنك من خلالها نستنتج كيف يمكنك الكتابة الخاصة بك.

آخر حل بسيط أن عملت بشكل جيد بالنسبة لي هو الاستفادة من دفق Ado الدرجة:

void PrettySaveXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, const wchar_t* filePath)
{
    ADODB::_StreamPtr stream(__uuidof(ADODB::Stream));
    stream->Type = ADODB::adTypeBinary;
    stream->Open(vtMissing, ADODB::adModeUnknown, ADODB::adOpenStreamUnspecified, _bstr_t(), _bstr_t());
    PrettyWriteXmlDocument(xmlDoc, IStreamPtr(stream));
    stream->SaveToFile(filePath, ADODB::adSaveCreateOverWrite);
}

التغرية معا

التبسيط main وظيفة يظهر في هذا العمل:

#include <stdlib.h>
#include <objbase.h>
#include <comutil.h>
#include <comdef.h>
#include <comdefsp.h>
#import <msxml6.dll>
#import <msado60.tlb> rename("EOF", "EndOfFile")  // requires: /I $(CommonProgramFiles)\System\ado


void PrettyWriteXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, IStream* stream);
void PrettySaveXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, const wchar_t* filePath);


int wmain()
{
    CoInitializeEx(nullptr, COINIT_MULTITHREADED);

    try
    {
        MSXML2::IXMLDOMDocumentPtr xmlDoc(__uuidof(MSXML2::DOMDocument60));
        xmlDoc->appendChild(xmlDoc->createElement(L"root"));

        PrettySaveXmlDocument(xmlDoc, L"xmldoc.xml");
    }
    catch (const _com_error&)
    {
    }

    CoUninitialize();

    return EXIT_SUCCESS;
}


// assume definitions of PrettyWriteXmlDocument and PrettySaveXmlDocument go here

وإذا لم المكتبة لديها خيار تنسيق ثم في الاتجاه الآخر الوحيد هو استخدام XSLT، أو طابعة جميلة الخارجية (على ما أظن htmltidy يمكن أيضا القيام أكس) doen't يبدو أن هناك خيارا في ليب codeproject ولكن يمكنك تحديد أنماط XSLT لMSXML.

ولقد كتب السيناريو الحوار الاقتصادي الاستراتيجي في حين يعود لالطعج أكس الأساسي. يمكنك استخدامه بمثابة إندينتر الخارجي إذا فشل كل شيء آخر (حفظ هذا xmlindent.sed، ومعالجة أكس مع الحوار الاقتصادي الاستراتيجي -f xmlindent.sed <اسم> ). قد تحتاج سيغوين أو بعض بيئة POSIX أخرى لاستخدامها بالرغم من ذلك.

وهنا يكمن مصدر:

:a
/>/!N;s/\n/ /;ta
s/  / /g;s/^ *//;s/  */ /g
/^<!--/{
:e
/-->/!N;s/\n//;te
s/-->/\n/;D;
}
/^<[?!][^>]*>/{
H;x;s/\n//;s/>.*$/>/;p;bb
}
/^<\/[^>]*>/{
H;x;s/\n//;s/>.*$/>/;s/^    //;p;bb
}
/^<[^>]*\/>/{
H;x;s/\n//;s/>.*$/>/;p;bb
}
/^<[^>]*[^\/]>/{
H;x;s/\n//;s/>.*$/>/;p;s/^/ /;bb
}
/</!ba
{
H;x;s/\n//;s/ *<.*$//;p;s/[^    ].*$//;x;s/^[^<]*//;ba
}
:b
{
s/[^    ].*$//;x;s/^<[^>]*>//;ba
}

وHrmp، تبدو علامات التبويب لتكون مشوه ... يمكنك نسخ النفايات من هنا بدلا من ذلك: <لأ href = "http://mitchnull.blogspot.com/2008/09/xml-indenting-with-sed1.html "يختلط =" نوفولو noreferrer "> XML الطعج مع الحوار الاقتصادي الاستراتيجي (1)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top