/*---------------------------------------------------------------------- | TestMakeStandalone +---------------------------------------------------------------------*/ static void TestMakeStandalone() { const char* xml = "<parent xmlns:foo='foo-ns' xmlns:bar='bar-ns' xmlns='default-ns'><inter xmlns:bli='bli-ns' xmlns:bou='bou-ns'><child><foo:a>a-text</foo:a><bar:b xml:fifi='0'>b-text</bar:b><c>c-text</c><d bou:att='b-att'/></child></inter></parent>"; const char* expected = "<child xmlns=\"default-ns\" xmlns:foo=\"foo-ns\" xmlns:bar=\"bar-ns\" xmlns:bou=\"bou-ns\"><foo:a>a-text</foo:a><bar:b xml:fifi=\"0\">b-text</bar:b><c>c-text</c><d bou:att=\"b-att\"/></child>"; NPT_XmlParser parser; NPT_XmlNode* root = NULL; NPT_Result result = parser.Parse(xml, root); CHECK(NPT_SUCCEEDED(result)); CHECK(root != NULL); CHECK(root->AsElementNode() != NULL); NPT_XmlElementNode* inter = root->AsElementNode()->GetChild("inter", NPT_XML_ANY_NAMESPACE); CHECK(inter != NULL); NPT_XmlElementNode* child = inter->GetChild("child", NPT_XML_ANY_NAMESPACE); CHECK(child != NULL); child->MakeStandalone(); NPT_XmlWriter writer; NPT_MemoryStream buffer; writer.Serialize(*child, buffer); CHECK(buffer.GetBuffer() == NPT_DataBuffer(expected, NPT_StringLength(expected))); delete root; }
/*---------------------------------------------------------------------- | TestWhitespace +---------------------------------------------------------------------*/ static void TestWhitespace() { const char* xml = "<doc>\r\n" " <clean> </clean>\r\n" " <dirty> A B </dirty>\r\n" " <mixed>\r\n" " A\r\n" " <clean> </clean>\r\n" " B\r\n" " <dirty> A B </dirty>\r\n" " C\r\n" " </mixed>\r\n" "</doc>\r\n"; const char* expect1 = "<doc><clean/><dirty> A B </dirty><mixed>\n" " A\n" " <clean/>\n" " B\n" " <dirty> A B </dirty>\n" " C\n" " </mixed></doc>"; const char* expect2 = "<doc>\n" " <clean> </clean>\n" " <dirty> A B </dirty>\n" " <mixed>\n" " A\n" " <clean> </clean>\n" " B\n" " <dirty> A B </dirty>\n" " C\n" " </mixed>\n" "</doc>"; NPT_XmlParser parser1(false); // ignore whitespace NPT_XmlNode* root; CHECK(NPT_SUCCEEDED(parser1.Parse(xml, root))); CHECK(root); NPT_XmlWriter writer; NPT_MemoryStream buffer; writer.Serialize(*root, buffer); CHECK(buffer.GetBuffer() == NPT_DataBuffer(expect1, NPT_StringLength(expect1))); delete root; NPT_XmlParser parser2(true); // keep whitespace CHECK(NPT_SUCCEEDED(parser2.Parse(xml, root))); CHECK(root); buffer.SetSize(0); writer.Serialize(*root, buffer); CHECK(buffer.GetBuffer() == NPT_DataBuffer(expect2, NPT_StringLength(expect2))); delete root; }
/*---------------------------------------------------------------------- | TestCdata +---------------------------------------------------------------------*/ static void TestCdata() { const char* xml = "<doc> blabla <![CDATA[ < [[ Smith ]] > ]]> blibli</doc>"; const char* expect = "<doc> blabla < [[ Smith ]] > blibli</doc>"; NPT_XmlParser parser; NPT_XmlNode* root; CHECK(NPT_SUCCEEDED(parser.Parse(xml, root))); CHECK(root); NPT_XmlWriter writer; NPT_MemoryStream buffer; writer.Serialize(*root, buffer); CHECK(buffer.GetBuffer() == NPT_DataBuffer(expect, NPT_StringLength(expect))); delete root; }
/*---------------------------------------------------------------------- | TestComments +---------------------------------------------------------------------*/ static void TestComments() { const char* xml = "<!-- comment outside the element -->\n" "<doc> blabla <!-- --> foo <!-- you <g> &foo -> &bar --> blibli</doc>"; const char* expect = "<doc> blabla foo blibli</doc>"; NPT_XmlParser parser; NPT_XmlNode* root; CHECK(NPT_SUCCEEDED(parser.Parse(xml, root))); CHECK(root); NPT_XmlWriter writer; NPT_MemoryStream buffer; writer.Serialize(*root, buffer); CHECK(buffer.GetBuffer() == NPT_DataBuffer(expect, NPT_StringLength(expect))); delete root; }
/*---------------------------------------------------------------------- | TestWriter +---------------------------------------------------------------------*/ static void TestWriter() { NPT_XmlElementNode* top = new NPT_XmlElementNode("top"); NPT_XmlElementNode* child1 = new NPT_XmlElementNode("child1"); child1->SetAttribute("someAttribute", "someValue"); top->AddChild(child1); NPT_XmlElementNode* child2 = new NPT_XmlElementNode("child2"); child2->SetAttribute("someOtherAttribute", "someOtherValue"); child2->AddText("Some Text"); child1->AddChild(child2); NPT_XmlElementNode* child3 = new NPT_XmlElementNode("child3"); child3->SetAttribute("thirdArrtibute", "3"); child2->AddChild(child3); NPT_XmlWriter writer; NPT_File out(NPT_FILE_STANDARD_OUTPUT); out.Open(NPT_FILE_OPEN_MODE_WRITE); NPT_OutputStreamReference out_stream; out.GetOutputStream(out_stream); writer.Serialize(*top, *out_stream); }
/*---------------------------------------------------------------------- | TestSerializer +---------------------------------------------------------------------*/ static void TestSerializer() { NPT_XmlWriter writer; NPT_MemoryStream output; NPT_String check; NPT_LargeSize size; // // test without namespaces // // simple element with no prefix and no namespace NPT_XmlElementNode* top = new NPT_XmlElementNode("top"); writer.Serialize(*top, output); output.GetSize(size); check.Assign((const char*)output.GetData(), (NPT_Size)size); CHECK(check == "<top/>"); // with one attribute output.SetSize(0); top->SetAttribute("attr1", "b&w"); writer.Serialize(*top, output); output.GetSize(size); check.Assign((const char*)output.GetData(), (NPT_Size)size); CHECK(check == "<top attr1=\"b&w\"/>"); // add one child output.SetSize(0); delete top; top = new NPT_XmlElementNode("top"); NPT_XmlElementNode* child1 = new NPT_XmlElementNode("child1"); top->AddChild(child1); writer.Serialize(*top, output); output.GetSize(size); check.Assign((const char*)output.GetData(), (NPT_Size)size); CHECK(check == "<top><child1/></top>"); // // test with namespaces // // test default namespaces output.SetSize(0); delete top; top = new NPT_XmlElementNode("top"); top->SetNamespaceUri("", "http://namespace.com"); writer.Serialize(*top, output); output.GetSize(size); check.Assign((const char*)output.GetData(), (NPT_Size)size); CHECK(check == "<top xmlns=\"http://namespace.com\"/>"); // test attribute prefixes output.SetSize(0); delete top; top = new NPT_XmlElementNode("top"); top->SetAttribute(NULL, "foo", "6"); top->SetAttribute("ns1", "foo", "3"); top->SetAttribute("ns2", "foo", "4"); top->SetAttribute("ns1", "foo", "5"); writer.Serialize(*top, output); output.GetSize(size); check.Assign((const char*)output.GetData(), (NPT_Size)size); CHECK(check == "<top foo=\"6\" ns1:foo=\"5\" ns2:foo=\"4\"/>"); delete top; }
/*---------------------------------------------------------------------- | TestNamespaces +---------------------------------------------------------------------*/ static void TestNamespaces() { NPT_XmlElementNode* top = new NPT_XmlElementNode("top"); top->SetNamespaceUri("", "http://namespace1.com"); CHECK(top->GetNamespaceUri("") && *(top->GetNamespaceUri("")) == "http://namespace1.com"); NPT_XmlElementNode* child1 = new NPT_XmlElementNode("child1"); top->AddChild(child1); CHECK(child1->GetNamespaceUri("")); CHECK(*(child1->GetNamespaceUri("")) == "http://namespace1.com"); NPT_XmlElementNode* child2 = new NPT_XmlElementNode("ns1", "child2"); top->AddChild(child2); CHECK(child2->GetNamespaceUri("")); CHECK(*(child2->GetNamespaceUri("")) == "http://namespace1.com"); CHECK(child2->GetNamespaceUri("ns1") == NULL); child2->SetNamespaceUri("ns1", "http://blabla"); CHECK(child2->GetNamespaceUri("ns1")); CHECK(*child2->GetNamespaceUri("ns1") == "http://blabla"); CHECK(*child2->GetNamespace() == "http://blabla"); // testing a child with a namespace defined in parent NPT_XmlElementNode* child3 = new NPT_XmlElementNode("ns1", "child3"); child2->AddChild(child3); CHECK(child3->GetNamespaceUri("")); CHECK(*(child3->GetNamespaceUri("")) == "http://namespace1.com"); CHECK(child3->GetNamespaceUri("ns1")); CHECK(*child3->GetNamespaceUri("ns1") == "http://blabla"); CHECK(*child3->GetNamespace() == "http://blabla"); // testing adding a namespace in a node which namespace is defined in parent child3->SetNamespaceUri("ns3", "http://foofoo"); CHECK(child3->GetNamespaceUri("ns1")); CHECK(*child3->GetNamespaceUri("ns1") == "http://blabla"); CHECK(*child3->GetNamespace() == "http://blabla"); const char* xml1 = "<top>" " <child1 xmlns:foo='blabla'><cc1 foo:attr1='0'/></child1>" " <child2 xmlns='foobar' attr1='1'>" " <cc2/>" " <cc3 />" " </child2 >" " <ns2:child3 xmlns:ns2='abcd'><cc3/></ns2:child3>" " <child4 ns3:attr1='3' xmlns:ns3='efgh'>" " <ns3:cc4 ns3:attr1='4'/>" " </child4>" "</top>"; NPT_XmlParser parser; NPT_XmlNode* root = NULL; NPT_Result result = parser.Parse(xml1, root); CHECK(NPT_SUCCEEDED(result)); CHECK(root != NULL); NPT_XmlWriter writer; NPT_MemoryStream output; writer.Serialize(*root, output); NPT_LargeSize size; output.GetSize(size); printf(NPT_String((const char*)output.GetData(), (NPT_Size)size).GetChars()); delete top; delete root; // test default and empty namespaces const char* xml2 = "<top><a></a><b xmlns='foo'><c xmlns=''></c></b></top>"; result = parser.Parse(xml2, root); CHECK(root->AsElementNode()->GetNamespace() == NULL); NPT_XmlElementNode* a_elem = (*root->AsElementNode()->GetChildren().GetItem(0))->AsElementNode(); CHECK(a_elem->GetNamespace() == NULL); NPT_XmlElementNode* b_elem = (*root->AsElementNode()->GetChildren().GetItem(1))->AsElementNode(); CHECK(*b_elem->GetNamespace() == "foo"); NPT_XmlElementNode* c_elem = (*b_elem->GetChildren().GetItem(0))->AsElementNode(); CHECK(c_elem->GetNamespace() == NULL); delete root; }
/*---------------------------------------------------------------------- | CMediaCrawler::UpdateDidl +---------------------------------------------------------------------*/ NPT_String CMediaCrawler::UpdateDidl(const char* server_uuid, const NPT_String& didl, NPT_SocketInfo* info) { NPT_String new_didl; NPT_String str; NPT_XmlNode* node = NULL; NPT_XmlWriter writer; NPT_OutputStreamReference stream(new NPT_StringOutputStream(&new_didl)); NPT_LOG_FINE("Parsing Didl..."); NPT_XmlElementNode* tree = NULL; NPT_XmlParser parser; if (NPT_FAILED(parser.Parse(didl, node)) || !node || !node->AsElementNode()) { goto cleanup; } tree = node->AsElementNode(); NPT_LOG_FINE("Processing Didl xml..."); if (tree->GetTag().Compare("DIDL-Lite", true)) { goto cleanup; } // iterate through children NPT_Result res; for (NPT_List<NPT_XmlNode*>::Iterator children = tree->GetChildren().GetFirstItem(); children; children++) { NPT_XmlElementNode* child = (*children)->AsElementNode(); if (!child) continue; // object id remapping NPT_XmlAttribute* attribute_id; res = PLT_XmlHelper::GetAttribute(child, "id", attribute_id); if (NPT_SUCCEEDED(res) && attribute_id) { attribute_id->SetValue(FormatObjectId(server_uuid, attribute_id->GetValue())); } // parent ID remapping NPT_XmlAttribute* attribute_parent_id; res = PLT_XmlHelper::GetAttribute(child, "parentID", attribute_parent_id); if (NPT_SUCCEEDED(res)) { attribute_parent_id->SetValue(attribute_parent_id->GetValue().Compare("-1")?FormatObjectId(server_uuid, attribute_parent_id->GetValue()):"0"); } // resources remapping NPT_Array<NPT_XmlElementNode*> res; PLT_XmlHelper::GetChildren(child, res, "res"); if (res.GetItemCount() > 0) { for (unsigned int i=0; i<res.GetItemCount(); i++) { NPT_XmlElementNode* resource = res[i]; NPT_XmlAttribute* attribute_prot; const NPT_String* url; if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(resource, "protocolInfo", attribute_prot)) && (url = resource->GetText())) { // special case for Windows Media Connect // When a browse is done on the same machine, WMC uses localhost // instead of the IP for all resources urls which means we cannot advertise that // since it would be useless for a remote device // so we try to replace it with the right IP address by looking at which interface we received the // initial browse request on to make sure the remote device will be able to access the modified resource // urls (in case the local PC has more than 1 NICs) // replace the url NPT_List<NPT_XmlNode*>& children = resource->GetChildren(); NPT_HttpUrl http_url(NPT_Uri::PercentDecode(*url)); if ((http_url.GetHost() == "localhost" || http_url.GetHost() == "127.0.0.1") && info) { if (info->local_address.GetIpAddress().AsLong()) { http_url.SetHost(info->local_address.GetIpAddress().ToString()); // replace text children.Apply(NPT_ObjectDeleter<NPT_XmlNode>()); children.Clear(); resource->AddText(http_url.ToString()); url = resource->GetText(); } } CStreamHandler* handler = NULL; NPT_Result res = NPT_ContainerFind(m_StreamHandlers, CStreamHandlerFinder(attribute_prot->GetValue(), *url), handler); if (NPT_SUCCEEDED(res)) { handler->ModifyResource(resource); } } } } } // serialize modified node into new didl writer.Serialize(*node, *stream); delete node; return new_didl; cleanup: delete node; return didl; }