gpt4 book ai didi

c++ - 使用 C++/MSXML 中的变音符号根据嵌入式 XSD 资源验证 XML 文件

转载 作者:太空宇宙 更新时间:2023-11-04 13:47:33 28 4
gpt4 key购买 nike

我想使用 MSXML6 解析器验证 C++ 中的 XML 文件,并已按照 http://msdn.microsoft.com/en-us/library/ms762774%28v=vs.85%29.aspx 上的说明进行操作.但是,我正在处理的项目需要将 XSD 架构嵌入到二进制文件中。

这是应该验证的 XML 文件(为演示目的简化了所有文件):

<?xml version="1.0" encoding="UTF-8"?>
<Document xsi:schemaLocation="urn:test schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:test">
<Party>
<Id>1</Id>
<Name>Bob</Name>
<Salary>100.00</Salary>
</Party>
<Party>
<Id>2</Id>
<Name>Alice</Name>
<Salary>200.00</Salary>
</Party>
<Party>
<Id>3</Id>
<Name>Günther</Name>
<Salary>300.00</Salary>
</Party>
</Document>

这是 XSD 架构:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xs:schema xmlns="urn:test" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test" elementFormDefault="qualified">

<xs:simpleType name="NameType">
<xs:restriction base="xs:string">
<xs:pattern value="([A-Za-z0-9ÄÖÜäöü]){1,10}"/>
</xs:restriction>
</xs:simpleType>

<xs:complexType name="PartyType">
<xs:sequence>
<xs:element name="Id" type="xs:integer"/>
<xs:element name="Name" type="NameType"/>
<xs:element name="Salary" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>

<xs:element name="Document">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="9999999">
<xs:element name="Party" type="PartyType"/>
</xs:choice>
</xs:complexType>
</xs:element>

</xs:schema>

上述 XSD 模式作为 Win32 资源嵌入到可执行文件中,可以通过标识符“IDR_XSDSCHEMA1”引用(参见选项 1 的注释行):

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#import <msxml6.dll>
#include "resource.h"

// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) return bstrResult; } while(0)

//Method for acquiring own handle
HMODULE GetThisDllHandle()
{
MEMORY_BASIC_INFORMATION info;
size_t len = VirtualQueryEx(GetCurrentProcess(), (void*)GetThisDllHandle, &info, sizeof(info));
return len ? (HMODULE)info.AllocationBase : NULL;
}

_bstr_t validateFile(_bstr_t bstrFile)
{
//Schema collection
MSXML2::IXMLDOMSchemaCollectionPtr pXS;

//XML document
MSXML2::IXMLDOMDocument2Ptr pXD;

//XSD document
MSXML2::IXMLDOMDocument2Ptr pXSD;

//Validation object
MSXML2::IXMLDOMParseErrorPtr pErr;

_bstr_t bstrResult = L"";
HRESULT hr = S_OK;

//Load XSD schema from resource
HMODULE handle = GetThisDllHandle();
HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(IDR_XSDSCHEMA1), L"XSDSCHEMA");
HGLOBAL rcData = ::LoadResource(handle, rc);
LPVOID data = (::LockResource(rcData));
::FreeResource(rcData);

//Load schema stream into document
CHK_HR(pXSD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));

if (pXSD->loadXML((LPCSTR)data) != VARIANT_TRUE)
return bstrResult;

// Create a schema cache
CHK_HR(pXS.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER));

//--> OPTION 1: VALIDATING AGAINST EMBEDDED XSD RESOURCE; DOESN'T WORK <--
CHK_HR(pXS->add(L"urn:test", pXSD.GetInterfacePtr()));

//--> OPTION 2: VALIDATING AGAINST PHYSICAL XSD FILE; WORKS FINE <--
//CHK_HR(pXS->add(L"urn:test", L"schema.xsd"));

// Create a DOMDocument and set its properties.
CHK_HR(pXD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));

pXD->async = VARIANT_FALSE;
pXD->validateOnParse = VARIANT_TRUE;
pXD->preserveWhiteSpace = VARIANT_TRUE;

//Assign the schema cache to the Document's schema collection
pXD->schemas = pXS.GetInterfacePtr();

//Load XML file
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());
}

else
{
bstrResult = _bstr_t(L"Validation succeeded for ") + bstrFile +
_bstr_t(L"\n======================\n") +
_bstr_t(pXD->xml);
}

return bstrResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitialize(NULL);
if(SUCCEEDED(hr))
{
try
{
_bstr_t bstrOutput = validateFile(L"Document.xml");
MessageBox(NULL, bstrOutput, L"schemaCache",MB_OK);
}

catch(_com_error &e)
{
MessageBox(NULL, e.Description(), L"schemaCache",MB_OK);
}
CoUninitialize();
}
return 0;
}

不幸的是,我在尝试运行验证例程时遇到了一些奇怪的行为(OPTION 1 评论)。看起来,XSD 资源中的变音符号在加载到流中时未正确解码。这会导致困惑的验证引用,如以下结果所示:

fail

但是,当模式文件直接从磁盘加载时(选项 2 注释),验证例程运行得很好:

ok2

我已经尝试将加载的流从 Unicode 转换为多字节,反之亦然,但无济于事。我在这里缺少什么吗?还是 Win32 资源仅限于特定字符集?感谢您的任何建议。

最佳答案

请参阅 WhozCraig 的评论: 使用 MultiByteToWideChar() 并将 CP_UTF8 作为输入参数返回有效的 Unicode 字符串。

关于c++ - 使用 C++/MSXML 中的变音符号根据嵌入式 XSD 资源验证 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25250987/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com