using namespace System;
using namespace System::IO;
using namespace System::Text;
using namespace System::Xml;
using namespace System::Xml::XPath;
using namespace System::Xml::Xsl;
public ref class ParseCdata
{
public:
ParseCdata(String^ xmlText) : doc(gcnew XmlDocument)
{
doc->LoadXml(xmlText);
}
String^ GetCData(XPathNodeIterator^ nodes)
{
StringBuilder^ result = gcnew StringBuilder;
while (nodes->MoveNext())
{
XPathNavigator^ nodesNav = nodes->Current;
String^ xpath = String::Format("/test/data[@id='{0}']",
nodes->Current->GetAttribute("id", String::Empty));
XmlNodeList^ dataNodes = doc->SelectNodes(xpath);
for each (XmlNode^ node in dataNodes)
{
for each (XmlNode^ child in node->ChildNodes)
{
if (child->NodeType == XmlNodeType::CDATA)
{
result->AppendFormat("-!!!{0}!!!-", child->Value);
}
}
}
}
return result->ToString();
}
private:
XmlDocument^ doc;
};
int main(array<System::String ^> ^args)
{
String^ xmlText =
"<?xml version='1.0'?>"
"<test>"
" <data id='1'><![CDATA[CDATA1]]><![CDATA[CDATA2]]></data>"
"</test>";
String^ xsltText =
"<?xml version='1.0'?>"
"<xsl:stylesheet version='1.0' "
" xmlns:xsl='http://www.w3.org/1999/XSL/Transform'"
" xmlns:extObj='urn:cdata-conv'>"
"<xsl:template match='/'>"
"<result>\n"
"\t<xsl:apply-templates select='test/data'/>\n"
"</result>\n"
"</xsl:template>"
"<xsl:template match='data'>"
"<xsl:value-of select='extObj:GetCData(.)'/>"
"</xsl:template>"
"</xsl:stylesheet>";
StringReader^ strReader1;
XmlReader^ xmlReader1;
StringReader^ strReader2;
XmlReader^ xmlReader2;
try
{
strReader1 = gcnew StringReader(xsltText);
xmlReader1 = XmlReader::Create(strReader1);
XslCompiledTransform^ xslt = gcnew XslCompiledTransform;
xslt->Load(xmlReader1);
strReader2 = gcnew StringReader(xmlText);
xmlReader2 = XmlReader::Create(strReader2);
XPathDocument^ xml = gcnew XPathDocument(xmlReader2);
XsltArgumentList^ xsltArgs = gcnew XsltArgumentList;
ParseCdata^ cdata = gcnew ParseCdata(xmlText);
xsltArgs->AddExtensionObject("urn:cdata-conv", cdata);
xslt->Transform(xml, xsltArgs, Console::Out);
}
catch (Exception^ excp)
{
Console::WriteLine(excp->ToString());
}
finally
{
if (xmlReader2 != nullptr)
xmlReader2->Close();
if (strReader2 != nullptr)
strReader2->Close();
if (xmlReader1 != nullptr)
xmlReader1->Close();
if (strReader1 != nullptr)
strReader1->Close();
}
return 0;
}