Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用casablanca(PPL)http_客户端返回的XmlLite处理XML?_C++_C++11_Asynchronous_Ppl_Xmllite - Fatal编程技术网

C++ 如何使用casablanca(PPL)http_客户端返回的XmlLite处理XML?

C++ 如何使用casablanca(PPL)http_客户端返回的XmlLite处理XML?,c++,c++11,asynchronous,ppl,xmllite,C++,C++11,Asynchronous,Ppl,Xmllite,我希望向web服务发出请求,获取XML内容,并对其进行解析以获取服务返回的特定值 代码将用原生C++11(MS Visual Studio 2013)编写。选择了PPL库。对于XML解析,选择了XmlLite 我习惯C++编程;然而,来自PPL库的异步任务编程——这种方法——对我来说是新的。我知道什么是异步编程,我知道并行编程的原理。然而,我不习惯使用continuations(.then(…)),我只是在慢慢地将我的脑袋绕到这个概念上 到目前为止,我已经修改了示例以获得XML结果并将其写入文本

我希望向web服务发出请求,获取XML内容,并对其进行解析以获取服务返回的特定值

代码将用原生C++11(MS Visual Studio 2013)编写。选择了PPL库。对于XML解析,选择了XmlLite

我习惯C++编程;然而,来自PPL库的异步任务编程——这种方法——对我来说是新的。我知道什么是异步编程,我知道并行编程的原理。然而,我不习惯使用continuations(
.then(…)
),我只是在慢慢地将我的脑袋绕到这个概念上

到目前为止,我已经修改了示例以获得XML结果并将其写入文本文件:

// Open a stream to the file to write the HTTP response body into.
auto fileBuffer = std::make_shared<concurrency::streams::streambuf<uint8_t>>();
file_buffer<uint8_t>::open(L"test.xml", std::ios::out)
    .then([=](concurrency::streams::streambuf<uint8_t> outFile) -> pplx::task < http_response >
{
    *fileBuffer = outFile;

    // Create an HTTP request.
    // Encode the URI query since it could contain special characters like spaces.
    // Create http_client to send the request.
    http_client client(L"http://api4.mapy.cz/");

    // Build request URI and start the request.
    uri_builder builder(L"/geocode");
    builder.append_query(L"query", address);

    return client.request(methods::GET, builder.to_string());
})

    // Write the response body into the file buffer.
    .then([=](http_response response) -> pplx::task<size_t>
{
    printf("Response status code %u returned.\n", response.status_code());

    return response.body().read_to_end(*fileBuffer);
})

    // Close the file buffer.
    .then([=](size_t)
{
    return fileBuffer->close();
})

    // Wait for the entire response body to be written into the file.
    .wait();
实际上,目标不是将流写入
test.xml
文件以向XmlLite解析器提供数据。XML非常小,它包含一个或多个(如果地址不明确)具有我要提取的x和y属性的item元素,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<result>
    <point query="Vítězství 27, Olomouc">
        <item
                x="17.334045"
                y="49.619723"
                id="9025034"
                source="addr"
                title="Vítězství 293/27, Olomouc, okres Olomouc, Česká republika"
        />
        <item
                x="17.333067"
                y="49.61618"
                id="9024797"
                source="addr"
                title="Vítězství 27/1, Olomouc, okres Olomouc, Česká republika"
        />
    </point>
</result>


我不需要那个
test.xml
文件。如何获取流以及如何将其重定向到XmlLite解析器?

我还没有使用卡萨布兰卡,因此这可能有点不合适。(我很想与卡萨布兰卡合作,但我必须先争取更多的时间。)也就是说,您显示的代码似乎将下载一个xml文件并将其保存到本地文件
test.xml
。从这一点来看,如果xml文件是用UTF-8编码的,那么将该文件加载到XmlLite中就很简单了。如果它不是UTF-8,你将不得不跳转通过一些额外的环来解码它,无论是在内存中还是通过or,我在这里不做介绍

获得UTF-8文件或处理编码后,使用XmlLite启动XML解析的最简单方法如以下文档所示:

在您的情况下,您希望跳过该文件,因此需要在内存中创建一个
IStream
。您有三个主要选择:

  • 将字符串视为内存缓冲区并使用
  • 从卡萨布兰卡流到使用创建的
    IStream
    ,然后在完成检索后将其用作源
  • 为卡萨布兰卡的
    concurrency::streams::IStream
    创建一个
    IStream
    包装器,将其异步性隐藏在
    IStream
    接口后面
  • 一旦你有了你的流,你就必须告诉你的读者

    无论上述选项如何,我建议对显示为
    pFileStream
    pReader
    的变量使用诸如ATL的
    CComPtr
    CComPtr
    之类的RAII类,或我建议的
    pMemStream
    。这也是您需要处理比XmlLite默认值更深的递归的时候。然后就是读取文件。方法中记录的最简单的循环;以下是一些最重要的部分,但请注意,为了可读性,我省略了错误检测:

    void Summarize(IXmlReader *pReader, LPCWSTR wszType)
    {
        LPCWSTR wszNamespaceURI, wszPrefix, wszLocalName, wszValue;
        UINT cchNamespaceURI, cchPrefix, cchLocalName, cchValue;
    
        pReader->GetNamespaceURI(&wszNamespaceURI, &cchNamespaceURI);
        pReader->GetPrefix(&wszPrefix, &cchPrefix);
        pReader->GetLocalName(&wszLocalName, &cchLocalName);
        pReader->GetValue(&wszValue, &cchValue);
        std::wcout << wszType << L": ";
        if (cchNamespaceURI) std::wcout << L"{" << wszNamespaceURI << L"} ";
        if (cchPrefix)       std::wcout << wszPrefix << L":";
        std::wcout << wszLocalName << "='" << wszValue << "'\n";
    }
    
    void Parse(IXmlReader *pReader)
    {
        // Read through each node until the end
        while (!pReader->IsEOF())
        {
            hr = pReader->Read(&nodeType);
            if (hr != S_OK)
                break;
    
            switch (nodeType)
            {
                //  : : :
    
                case XmlNodeType_Element:
                    Summarize(pReader, L"BeginElement");
                    while (S_OK == pReader->MoveToNextAttribute())
                        Summarize(pReader, L"Attribute");
                    pReader->MoveToElement();
                    if (pReader->IsEmptyElement())
                        std::wcout << L"EndElement\n";
                    break;
    
                case XmlNodeType_EndElement:
                    std::wcout << L"EndElement\n";
                    break;
    
                //  : : :
             }
        }
    }
    
    void摘要(IXmlReader*pReader,LPCWSTR wszType)
    {
    lpcwsstr wszNamespaceURI、wszPrefix、wszLocalName、wszValue;
    UINT cchNamespaceURI、cchPrefix、cchLocalName、cchValue;
    pReader->GetNamespaceURI(&wszNamespaceURI,&cchNamespaceURI);
    pReader->GetPrefix(&wszPrefix,&cchPrefix);
    pReader->GetLocalName(&wszLocalName,&cchLocalName);
    预订单->获取值(&wszValue,&cchValue);
    
    std::wcout谢谢,Michael。请看一下更新后的问题。更新部分之前的文本保持不变。@pepr执行我添加的关于
    SHCreateMemStream
    /
    CreateStreamOnHGlobal
    的部分,包括您要查找的内容吗?我现在专门阅读请求,以避免击中文件系统。记住编码在这里仍然是有意义的,因此在我使用XmlLite
    std::string
    (持有UTF-8)的经验中,它通常比
    std::wstring
    更简单。坦率地说,我还没有尝试过。我明天会看一看。现在看一看,它似乎是
    响应。body()。read_to_end()
    或类似的方法应该能够为XmlLite流提供信息。对于编码,提取的信息将是数字。此外,
    wxString
    接受将
    char*
    字符串解释为UTF-8编码字符串。我将询问细节,我接受答案。我明天将进行实验。无论如何,赏金是你的。
    //Open read-only input stream
    if (FAILED(hr = SHCreateStreamOnFile(argv[1], STGM_READ, &pFileStream)))
    {
        wprintf(L"Error creating file reader, error is %08.8lx", hr);
        return -1;
    }
    
    if (FAILED(hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &pReader, NULL)))
    {
        wprintf(L"Error creating xml reader, error is %08.8lx", hr);
        return -1;
    }
    
    hr = pReader->SetInput(pStream);
    
    void Summarize(IXmlReader *pReader, LPCWSTR wszType)
    {
        LPCWSTR wszNamespaceURI, wszPrefix, wszLocalName, wszValue;
        UINT cchNamespaceURI, cchPrefix, cchLocalName, cchValue;
    
        pReader->GetNamespaceURI(&wszNamespaceURI, &cchNamespaceURI);
        pReader->GetPrefix(&wszPrefix, &cchPrefix);
        pReader->GetLocalName(&wszLocalName, &cchLocalName);
        pReader->GetValue(&wszValue, &cchValue);
        std::wcout << wszType << L": ";
        if (cchNamespaceURI) std::wcout << L"{" << wszNamespaceURI << L"} ";
        if (cchPrefix)       std::wcout << wszPrefix << L":";
        std::wcout << wszLocalName << "='" << wszValue << "'\n";
    }
    
    void Parse(IXmlReader *pReader)
    {
        // Read through each node until the end
        while (!pReader->IsEOF())
        {
            hr = pReader->Read(&nodeType);
            if (hr != S_OK)
                break;
    
            switch (nodeType)
            {
                //  : : :
    
                case XmlNodeType_Element:
                    Summarize(pReader, L"BeginElement");
                    while (S_OK == pReader->MoveToNextAttribute())
                        Summarize(pReader, L"Attribute");
                    pReader->MoveToElement();
                    if (pReader->IsEmptyElement())
                        std::wcout << L"EndElement\n";
                    break;
    
                case XmlNodeType_EndElement:
                    std::wcout << L"EndElement\n";
                    break;
    
                //  : : :
             }
        }
    }