I am using the XmlLite library to create an XML file. I want the resulting XML file's prolog to not include the encoding attribute (just the version):
<?xml version="1.0"?>
Here is my code:
HRESULT hr = S_OK;
IStream *pOutFileStream = NULL;
IXmlWriter *pWriter = NULL;
CComPtr<IXmlWriterOutput> pWriterOutput;
//Open writeable output stream
if (FAILED(hr = SHCreateStreamOnFile(output_file_name, STGM_CREATE | STGM_WRITE, &pOutFileStream)))
{
wprintf(L"Error creating file writer, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = CreateXmlWriter(__uuidof(IXmlWriter), (void**) &pWriter, NULL)))
{
wprintf(L"Error creating xml writer, error is %08.8lx", hr);
HR(hr);
}
if(FAILED(CreateXmlWriterOutputWithEncodingName(pOutFileStream, NULL, L"UTF-8", &pWriterOutput))){
wprintf(L"Error setting xml encoding, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = pWriter->SetOutput(pWriterOutput)))
{
wprintf(L"Error, Method: SetOutput, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = pWriter->SetProperty(XmlWriterProperty_Indent, 4)))
{
wprintf(L"Error, Method: SetProperty XmlWriterProperty_Indent, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = pWriter->WriteStartDocument(XmlStandalone_Omit)))
{
wprintf(L"Error, Method: WriteStartDocument, error is %08.8lx", hr);
HR(hr);
}
I have tried removing the call to CreateXmlWriterOutputWithEncodingName() but even then a default encoding attribute with UTF-8 is getting created.
I have also tried putting NULL as the third parameter to that function.
Assistance would be much appreciated!
The XML declaration is written by the WriteStartDocument method.
Instead of calling WriteStartDocument, you can call WriteProcessingInstruction with L"xml" as the name of the processing instruction to write the XML declaration the way you want, for example:
if (FAILED(hr = pWriter->WriteProcessingInstruction(L"xml", L"version=\"1.0\"")))
{
wprintf(L"Error, Method: WriteProcessingInstruction, error is %08.8lx", hr);
HR(hr);
}
This will write the XML declaration as <?xml version="1.0"?>.
Related
I am using Media Foundation to create a webcam viewer.
Critical to this application is that the webcam stream is horizontally mirrored.
I am using the Video Processor MFT
to achieve this.
Here's the relevant code to add the MFT:
void tryMirror(IMFPMediaPlayer* pPlayer) {
IMFTransform* pMFT = NULL;
IMFVideoProcessorControl* pVPC = NULL;
HRESULT hr = CoCreateInstance(CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pMFT));
if (FAILED(hr)) {
ShowHResultErrorMessage(L"CoCreateInstance(CLSID_VideoProcessorMFT, ...) failed", hr);
goto done;
}
hr = pMFT->QueryInterface(&pVPC);
if (FAILED(hr)) {
ShowHResultErrorMessage(L"pMFT->QueryInterface(&pVPC) failed", hr);
goto done;
}
hr = pVPC->SetMirror(MIRROR_HORIZONTAL);
if (FAILED(hr)) {
ShowHResultErrorMessage(L"pVPC->SetMirror(MIRROR_HORIZONTAL) failed", hr);
goto done;
}
hr = pPlayer->InsertEffect(pMFT, FALSE); // Not optional - critical functionality
if (FAILED(hr)) {
ShowHResultErrorMessage(L"m_pPlayer->InsertEffect(CLSID_VideoProcessorMFT) failed", hr);
goto done;
}
done:
SafeRelease(&pMFT);
SafeRelease(&pVPC);
}
// class CPreview implements IMFPMediaPlayerCallback as follows
void STDMETHODCALLTYPE CPreview::OnMediaPlayerEvent(MFP_EVENT_HEADER* pEventHeader) {
switch (pEventHeader->eEventType)
{
//...
case MFP_EVENT_TYPE_MEDIAITEM_SET:
OnMediaItemSet(MFP_GET_MEDIAITEM_SET_EVENT(pEventHeader));
break;
case MFP_EVENT_TYPE_PLAY:
OnMfpPlay(MFP_GET_PLAY_EVENT(pEventHeader));
break;
}
}
// Called after I set the webcam media source
void CPreview::OnMediaItemSet(MFP_MEDIAITEM_SET_EVENT* /*pEvent*/)
{
HRESULT hr = m_pPlayer->Play();
if (FAILED(hr)) {
ShowHResultErrorMessage(L"m_pPlayer->Play() failed", hr);
}
}
void CPreview::OnMfpPlay(MFP_PLAY_EVENT* pEvent) {
if (FAILED(pEvent->header.hrEvent)) {
ShowHResultErrorMessage(L"OnMfpPlay failed", pEvent->header.hrEvent);
WCHAR msg[1000];
HRESULT hr = StringCbPrintf(msg, sizeof(msg), L"Event type: 0x%X", pEvent->header.eEventType);
ShowErrorMessage(msg);
return;
}
}
void ShowHResultErrorMessage(PCWSTR errContext, HRESULT hrErr) {
_com_error err(hrErr);
LPCTSTR hrErrMsg = err.ErrorMessage();
WCHAR msg[1000];
HRESULT hr = StringCbPrintf(msg, sizeof(msg), L"%s (HRESULT=0x%X, %s)", errContext, hrErr, hrErrMsg);
if (SUCCEEDED(hr)) {
MessageBox(NULL, msg, L"Error", MB_ICONERROR);
}
}
On my development machine, this program runs without error, exactly as desired.
However, on a different user machine,
it fails with this error:
OnMfpPlay failed (HRESULT=0xC00D36B2, The request is invalid in the current state.)
That is,
this error comes through on the OnMediaPlayerEvent callback
of the IMFPMediaPlayerCallback object.
I do know a few things about the machine that this fails on:
The user has also run a modified version,
with the MFT set to optional, like so:
pPlayer->InsertEffect(pMFT, TRUE).
In this case, the program runs,
but the mirroring MFT has no effect.
The error is definitely caused by this MFT.
This user is running Windows 10, version 1909.
The Video Processor MFT is clearly available.
Its API claims to work - all HRESULTs are successful.
This error, "The request is invalid in the current state", could mean anything, and
I can't find any way to get more observability.
What does 'The request is invalid in the current state' mean?
Why is it generated by adding a Video Processor MFT, only on some machines?
How can I debug this with a more specific error?
I have to read XML files in C++ and we are using XMLLite the problem I have is that the first line of my XML specifies the encoding
<?xml version="1.0" encoding="ISO-8859-15"?>
and when I try to parse the file with XMLLite, I'm getting the error MX_E_ENCODINGSIGNATURE. If I remove the encoding part, the XML parses fine.
<?xml version="1.0"?>
So is it possible to programmatically tell XMLLite to ignore the encoding resp. what other options do I have?
One solution would be to write my own input stream class and suppress this header, and inject the short version, but it would be nicer to have a clean solution.
Even though the documentation says that XMLLite can not handle different encodings it seems that you can go around this by using IMultiLanguage2, which is mentioned in the documentation but no example is given.
So here is how to enable it:
#include <mlang.h>
XMLLiteReader::XMLLiteReader(void)
{
mLanguage = NULL;
mXMLLiteReader = NULL;
mCOMInitialized = false;
HRESULT hr;
if(CoInitialize(NULL) != S_OK)
return;
mCOMInitialized = true;
if((hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_ALL, IID_IMultiLanguage2, (void **)&mLanguage)) != S_OK)
return;
hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &mXMLLiteReader, NULL);
if(hr != S_OK)
{
mXMLLiteReader = NULL;
return;
}
hr = mXMLLiteReader->SetProperty(XmlReaderProperty_MultiLanguage, (LONG_PTR)mLanguage);
}
I'm validating XML files against XSD schemas as they do in the MSXML documentation example. I have the following code:
XMLSchemaValidation updateInfoSchema;
updateInfoSchema.DoInitialization(L"schema.xsd");
HRESULT hr = CoInitialize(NULL);
if(SUCCEEDED(hr))
{
try
{
_bstr_t bstrOutput = updateInfoSchema.validateFile(L"valid.xml");
}
catch(_com_error &e)
{
updateInfoSchema.dump_com_error(e);
}
CoUninitialize();
}
// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)
_bstr_t XMLSchemaValidation::validateFile(_bstr_t bstrFile)
{
// Declare and initialize variables
MSXML2::IXMLDOMSchemaCollectionPtr pXS;
MSXML2::IXMLDOMDocument2Ptr pXD;
MSXML2::IXMLDOMParseErrorPtr pErr;
_bstr_t bstrResult = L"";
HRESULT hr = S_OK;
// Create a schema cache and add xsd schema to it.
CHK_HR(pXS.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER));
CHK_HR(pXS->add(L"", (LPCSTR)(SchemaFileName.GetString())));
// Create a DOMDocument and set its properties.
CHK_HR(pXD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
// Assign the schema cache to the DOMDocument's schemas collection.
pXD->schemas = pXS.GetInterfacePtr();
// Load bstrFile into the DOM document.
pXD->async = VARIANT_FALSE;
pXD->validateOnParse = VARIANT_TRUE;
pXD->resolveExternals = VARIANT_TRUE;
if(pXD->load(bstrFile) != VARIANT_TRUE)
{
pErr = pXD->parseError;
bstrResult = _bstr_t(L"Validation failed on ") + bstrFile +
_bstr_t(L"\n=====================") +
_bstr_t(L"\nReason: ") + _bstr_t(pErr->Getreason()) +
_bstr_t(L"\nSource: ") + _bstr_t(pErr->GetsrcText()) +
_bstr_t(L"\nLine: ") + _bstr_t(pErr->Getline()) +
_bstr_t(L"\n");
}
else
{
bstrResult = _bstr_t(L"Validation succeeded for ") + bstrFile +
_bstr_t(L"\n======================\n") +
_bstr_t(pXD->xml) + _bstr_t(L"\n");
}
CleanUp:
return bstrResult;
}
XMLSchemaValidation::DoInitialization(CString XSDFileName) gets the XSD schema file name into the CString XMLSchemaValidation::SchemaFileName.
The code then follows the one in the MSXML example, but I get
First-chance exception at 0x76f9c41f (KernelBase.dll) in CSW.exe: Microsoft C++ exception: _com_error at memory location 0x04a7f014..
when code reaches CHK_HR(pXS->add(L"", (LPCSTR)(SchemaFileName.GetString())));. hr has -2146697210.
Can anyone tell me why this happens?
MSXML is throwing the HRESULT OBJECT_NOT_FOUND (0x800C0006) because the xml you are using does not specify a character set, as detailed in this question. Or MSXML cannot find the file.
I've been using WIC to encode multiple images to the JPEGXR format.
Occassionally, my program logs an error for the last LogAssert in the following snippet of my Encode function.
hr = m_pFactory->CreateEncoder(GUID_ContainerFormatWmp, NULL, &pEncoder);
LogAssert(SUCCEEDED(hr),"Failed to create encoder. Err: 0x%x", hr);
hr = pEncoder->Initialize(pOutputStream, WICBitmapEncoderNoCache);
LogAssert(SUCCEEDED(hr),"Failed to initialize encoder. Err: 0x%x", hr);
hr = pEncoder->CreateNewFrame(&pBitmapFrame, &pPropertyBag);
LogAssert(SUCCEEDED(hr),"Encoder failed to create new frame. Err: 0x%x", hr);
SetEncodingProperties(pPropertyBag);
hr = pBitmapFrame->Initialize(pPropertyBag);
LogAssert(SUCCEEDED(hr),"Failed to initialize pBitmapFrame with the given properties. Err: 0x%x", hr);
hr = pBitmapFrame->SetSize(rawWidth, rawHeight);
LogAssert(SUCCEEDED(hr),"Failed to set bitmap size. Err: 0x%x", hr);
WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR;
hr = pBitmapFrame->SetPixelFormat(&formatGUID);
if(FAILED(hr) || !IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR))
{
LogAssert(false,"Failed to set pixel format to GUID_WICPixelFormat24bppBGR. Err: 0x%x", hr);
}
I checked the dump file and it seems the returned formatGUID is GUID_WICPixelFormat24bpp RGB.
I have the following questions:
When does the SetPixel format return a different version? What are the factors that could cause it to return a different GUID?
I am always encoding to JPEGXR, and always applying the same properties. Why is the behavior of SetPixelFormat non-deterministic? Shouldn't it either always succeed, or always return GUID_WICPixelFormat24bppRGB?
If the RGB format is supported, why isn't BGR? It's just a change in order.
My code, was written with the help of examples here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ee719871(v=vs.85).aspx
This is an issue that can happen with concurrent calls to SetPixelFormat. I've heard it will be fixed in Windows 8.1.
I use atl and CComPtr, like this:
CComPtr<IXMLDOMDocument> xml_doc;
HRESULT hr = xml_doc.CoCreateInstance(__uuidof(DOMDocument))
...
HRESULT hr = xml_doc->createElement(CComBSTR(element_name.c_str()), &element);
...
etc
When I invoke xml_doc->save it saves xml without header. What the easiest way to add header?
solved:
HRESULT hr;
CComPtr<IXMLDOMProcessingInstruction> proc_instr;
hr = xml_out->createProcessingInstruction(L"xml", L"version=\"1.0\" encoding=\"UTF-8\"", &proc_instr);
if (FAILED(hr))
throw std::exception("Failed to create IXMLDOMDocument processing instruction");
CComPtr<IXMLDOMNode> first_child;
hr = xml_out->get_firstChild(&first_child);
if (FAILED(hr))
throw std::exception("Failed to get first child of IXMLDOMDocument");
hr = xml_out->insertBefore(proc_instr, CComVariant(first_child), NULL);
if (FAILED(hr))
throw std::exception("Failed to insert IXMLDOMDocument processing instruction");
hr = xml_out->save(CComVariant(header->output_file.c_str()));
if (FAILED(hr))
throw std::exception("Failed to save response XML to '" + header->output_file + "'");
http://msdn.microsoft.com/en-us/library/windows/desktop/ms755439(v=vs.85).aspx