blob: 5db2025f6cc4a3df9e2b57c85de1a43ec15de228 [file] [log] [blame]
// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "xfa/fxfa/parser/xfa_document_serialize.h"
#include "xfa/fde/xml/fde_xml_imp.h"
#include "xfa/fgas/crt/fgas_codepage.h"
#include "xfa/fxfa/parser/xfa_doclayout.h"
#include "xfa/fxfa/parser/xfa_document.h"
#include "xfa/fxfa/parser/xfa_localemgr.h"
#include "xfa/fxfa/parser/xfa_object.h"
#include "xfa/fxfa/parser/xfa_parser.h"
#include "xfa/fxfa/parser/xfa_parser_imp.h"
#include "xfa/fxfa/parser/xfa_script.h"
#include "xfa/fxfa/parser/xfa_utils.h"
CXFA_DataImporter::CXFA_DataImporter(CXFA_Document* pDocument)
: m_pDocument(pDocument) {
ASSERT(m_pDocument);
}
FX_BOOL CXFA_DataImporter::ImportData(IFX_FileRead* pDataDocument) {
IXFA_Parser* pDataDocumentParser = IXFA_Parser::Create(m_pDocument);
if (!pDataDocumentParser) {
return FALSE;
}
if (pDataDocumentParser->StartParse(pDataDocument, XFA_XDPPACKET_Datasets) !=
XFA_PARSESTATUS_Ready) {
pDataDocumentParser->Release();
return FALSE;
}
if (pDataDocumentParser->DoParse(NULL) < XFA_PARSESTATUS_Done) {
pDataDocumentParser->Release();
return FALSE;
}
CXFA_Node* pImportDataRoot = pDataDocumentParser->GetRootNode();
if (!pImportDataRoot) {
pDataDocumentParser->Release();
return FALSE;
}
CXFA_Node* pDataModel =
ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Datasets));
if (!pDataModel) {
pDataDocumentParser->Release();
return FALSE;
}
CXFA_Node* pDataNode = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Data));
if (pDataNode) {
pDataModel->RemoveChild(pDataNode);
}
if (pImportDataRoot->GetElementType() == XFA_Element::DataModel) {
while (CXFA_Node* pChildNode =
pImportDataRoot->GetNodeItem(XFA_NODEITEM_FirstChild)) {
pImportDataRoot->RemoveChild(pChildNode);
pDataModel->InsertChild(pChildNode);
}
} else {
CFDE_XMLNode* pXMLNode = pImportDataRoot->GetXMLMappingNode();
CFDE_XMLNode* pParentXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::Parent);
if (pParentXMLNode) {
pParentXMLNode->RemoveChildNode(pXMLNode);
}
pDataModel->InsertChild(pImportDataRoot);
}
m_pDocument->DoDataRemerge(FALSE);
pDataDocumentParser->Release();
return TRUE;
}
CFX_WideString XFA_ExportEncodeAttribute(const CFX_WideString& str) {
CFX_WideTextBuf textBuf;
int32_t iLen = str.GetLength();
for (int32_t i = 0; i < iLen; i++) {
switch (str[i]) {
case '&':
textBuf << FX_WSTRC(L"&amp;");
break;
case '<':
textBuf << FX_WSTRC(L"&lt;");
break;
case '>':
textBuf << FX_WSTRC(L"&gt;");
break;
case '\'':
textBuf << FX_WSTRC(L"&apos;");
break;
case '\"':
textBuf << FX_WSTRC(L"&quot;");
break;
default:
textBuf.AppendChar(str[i]);
}
}
return textBuf.MakeString();
}
CFX_WideString XFA_ExportEncodeContent(const CFX_WideStringC& str) {
CFX_WideTextBuf textBuf;
int32_t iLen = str.GetLength();
for (int32_t i = 0; i < iLen; i++) {
FX_WCHAR ch = str.GetAt(i);
if (!FDE_IsXMLValidChar(ch)) {
continue;
}
if (ch == '&') {
textBuf << FX_WSTRC(L"&amp;");
} else if (ch == '<') {
textBuf << FX_WSTRC(L"&lt;");
} else if (ch == '>') {
textBuf << FX_WSTRC(L"&gt;");
} else if (ch == '\'') {
textBuf << FX_WSTRC(L"&apos;");
} else if (ch == '\"') {
textBuf << FX_WSTRC(L"&quot;");
} else if (ch == ' ') {
if (i && str.GetAt(i - 1) != ' ') {
textBuf.AppendChar(' ');
} else {
textBuf << FX_WSTRC(L"&#x20;");
}
} else {
textBuf.AppendChar(str.GetAt(i));
}
}
return textBuf.MakeString();
}
static void XFA_SaveAttribute(CXFA_Node* pNode,
XFA_ATTRIBUTE eName,
const CFX_WideStringC& wsName,
FX_BOOL bProto,
CFX_WideString& wsOutput) {
CFX_WideString wsValue;
if ((!bProto && !pNode->HasAttribute((XFA_ATTRIBUTE)eName, bProto)) ||
!pNode->GetAttribute((XFA_ATTRIBUTE)eName, wsValue, FALSE)) {
return;
}
wsValue = XFA_ExportEncodeAttribute(wsValue);
wsOutput += FX_WSTRC(L" ");
wsOutput += wsName;
wsOutput += FX_WSTRC(L"=\"");
wsOutput += wsValue;
wsOutput += FX_WSTRC(L"\"");
}
static FX_BOOL XFA_DataExporter_AttributeSaveInDataModel(
CXFA_Node* pNode,
XFA_ATTRIBUTE eAttribute) {
FX_BOOL bSaveInDataModel = FALSE;
if (pNode->GetElementType() != XFA_Element::Image) {
return bSaveInDataModel;
}
CXFA_Node* pValueNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
if (!pValueNode || pValueNode->GetElementType() != XFA_Element::Value) {
return bSaveInDataModel;
}
CXFA_Node* pFieldNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
if (pFieldNode && pFieldNode->GetBindData() &&
eAttribute == XFA_ATTRIBUTE_Href) {
bSaveInDataModel = TRUE;
}
return bSaveInDataModel;
}
FX_BOOL XFA_DataExporter_ContentNodeNeedtoExport(CXFA_Node* pContentNode) {
CFX_WideString wsContent;
if (!pContentNode->TryContent(wsContent, FALSE, FALSE))
return FALSE;
ASSERT(pContentNode->IsContentNode());
CXFA_Node* pParentNode = pContentNode->GetNodeItem(XFA_NODEITEM_Parent);
if (!pParentNode || pParentNode->GetElementType() != XFA_Element::Value)
return TRUE;
CXFA_Node* pGrandParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
if (!pGrandParentNode || !pGrandParentNode->IsContainerNode())
return TRUE;
if (pGrandParentNode->GetBindData())
return FALSE;
CXFA_WidgetData* pWidgetData = pGrandParentNode->GetWidgetData();
XFA_Element eUIType = pWidgetData->GetUIType();
if (eUIType == XFA_Element::PasswordEdit) {
return FALSE;
}
return TRUE;
}
static void XFA_DataExporter_RecognizeXFAVersionNumber(
CXFA_Node* pTemplateRoot,
CFX_WideString& wsVersionNumber) {
wsVersionNumber.clear();
if (!pTemplateRoot) {
return;
}
CFX_WideString wsTemplateNS;
if (!pTemplateRoot->TryNamespace(wsTemplateNS)) {
return;
}
XFA_VERSION eVersion =
pTemplateRoot->GetDocument()->RecognizeXFAVersionNumber(wsTemplateNS);
if (eVersion == XFA_VERSION_UNKNOWN) {
eVersion = XFA_VERSION_DEFAULT;
}
wsVersionNumber.Format(L"%i.%i", eVersion / 100, eVersion % 100);
}
static void XFA_DataExporter_RegenerateFormFile_Changed(
CXFA_Node* pNode,
CFX_WideTextBuf& buf,
FX_BOOL bSaveXML = FALSE) {
CFX_WideString wsAttrs;
int32_t iAttrs = 0;
const uint8_t* pAttrs =
XFA_GetElementAttributes(pNode->GetElementType(), iAttrs);
while (iAttrs--) {
const XFA_ATTRIBUTEINFO* pAttr =
XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]);
if (pAttr->eName == XFA_ATTRIBUTE_Name ||
(XFA_DataExporter_AttributeSaveInDataModel(pNode, pAttr->eName) &&
!bSaveXML)) {
continue;
}
CFX_WideString wsAttr;
XFA_SaveAttribute(pNode, pAttr->eName, pAttr->pName, bSaveXML, wsAttr);
wsAttrs += wsAttr;
}
CFX_WideString wsChildren;
switch (pNode->GetObjectType()) {
case XFA_ObjectType::ContentNode: {
if (!bSaveXML && !XFA_DataExporter_ContentNodeNeedtoExport(pNode)) {
break;
}
CXFA_Node* pRawValueNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pRawValueNode &&
pRawValueNode->GetElementType() != XFA_Element::SharpxHTML &&
pRawValueNode->GetElementType() != XFA_Element::Sharptext &&
pRawValueNode->GetElementType() != XFA_Element::Sharpxml) {
pRawValueNode = pRawValueNode->GetNodeItem(XFA_NODEITEM_NextSibling);
}
if (!pRawValueNode) {
break;
}
CFX_WideString wsContentType;
pNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, FALSE);
if (pRawValueNode->GetElementType() == XFA_Element::SharpxHTML &&
wsContentType == FX_WSTRC(L"text/html")) {
CFDE_XMLNode* pExDataXML = pNode->GetXMLMappingNode();
if (!pExDataXML) {
break;
}
CFDE_XMLNode* pRichTextXML =
pExDataXML->GetNodeItem(CFDE_XMLNode::FirstChild);
if (!pRichTextXML) {
break;
}
IFX_MemoryStream* pMemStream = FX_CreateMemoryStream(TRUE);
IFX_Stream* pTempStream = IFX_Stream::CreateStream(
(IFX_FileWrite*)pMemStream, FX_STREAMACCESS_Text |
FX_STREAMACCESS_Write |
FX_STREAMACCESS_Append);
pTempStream->SetCodePage(FX_CODEPAGE_UTF8);
pRichTextXML->SaveXMLNode(pTempStream);
wsChildren += CFX_WideString::FromUTF8(
CFX_ByteStringC(pMemStream->GetBuffer(), pMemStream->GetSize()));
pTempStream->Release();
pMemStream->Release();
} else if (pRawValueNode->GetElementType() == XFA_Element::Sharpxml &&
wsContentType == FX_WSTRC(L"text/xml")) {
CFX_WideString wsRawValue;
pRawValueNode->GetAttribute(XFA_ATTRIBUTE_Value, wsRawValue, FALSE);
if (wsRawValue.IsEmpty()) {
break;
}
CFX_WideStringArray wsSelTextArray;
int32_t iStart = 0;
int32_t iEnd = wsRawValue.Find(L'\n', iStart);
iEnd = (iEnd == -1) ? wsRawValue.GetLength() : iEnd;
while (iEnd >= iStart) {
wsSelTextArray.Add(wsRawValue.Mid(iStart, iEnd - iStart));
iStart = iEnd + 1;
if (iStart >= wsRawValue.GetLength()) {
break;
}
iEnd = wsRawValue.Find(L'\n', iStart);
}
CXFA_Node* pParentNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
ASSERT(pParentNode);
CXFA_Node* pGrandparentNode =
pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
ASSERT(pGrandparentNode);
CFX_WideString bodyTagName;
bodyTagName = pGrandparentNode->GetCData(XFA_ATTRIBUTE_Name);
if (bodyTagName.IsEmpty()) {
bodyTagName = FX_WSTRC(L"ListBox1");
}
buf << FX_WSTRC(L"<");
buf << bodyTagName;
buf << FX_WSTRC(L" xmlns=\"\"\n>");
for (int32_t i = 0; i < wsSelTextArray.GetSize(); i++) {
buf << FX_WSTRC(L"<value\n>");
buf << XFA_ExportEncodeContent(wsSelTextArray[i].AsStringC());
buf << FX_WSTRC(L"</value\n>");
}
buf << FX_WSTRC(L"</");
buf << bodyTagName;
buf << FX_WSTRC(L"\n>");
wsChildren += buf.AsStringC();
buf.Clear();
} else {
CFX_WideStringC wsValue = pRawValueNode->GetCData(XFA_ATTRIBUTE_Value);
wsChildren += XFA_ExportEncodeContent(wsValue);
}
} break;
case XFA_ObjectType::TextNode:
case XFA_ObjectType::NodeC:
case XFA_ObjectType::NodeV: {
CFX_WideStringC wsValue = pNode->GetCData(XFA_ATTRIBUTE_Value);
wsChildren += XFA_ExportEncodeContent(wsValue);
} break;
default:
if (pNode->GetElementType() == XFA_Element::Items) {
CXFA_Node* pTemplateNode = pNode->GetTemplateNode();
if (!pTemplateNode ||
pTemplateNode->CountChildren(XFA_Element::Unknown) !=
pNode->CountChildren(XFA_Element::Unknown)) {
bSaveXML = TRUE;
}
}
CFX_WideTextBuf newBuf;
CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pChildNode) {
XFA_DataExporter_RegenerateFormFile_Changed(pChildNode, newBuf,
bSaveXML);
wsChildren += newBuf.AsStringC();
newBuf.Clear();
pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
}
if (!bSaveXML && !wsChildren.IsEmpty() &&
pNode->GetElementType() == XFA_Element::Items) {
wsChildren.clear();
bSaveXML = TRUE;
CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pChild) {
XFA_DataExporter_RegenerateFormFile_Changed(pChild, newBuf, bSaveXML);
wsChildren += newBuf.AsStringC();
newBuf.Clear();
pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);
}
}
break;
}
if (!wsChildren.IsEmpty() || !wsAttrs.IsEmpty() ||
pNode->HasAttribute(XFA_ATTRIBUTE_Name)) {
CFX_WideStringC wsElement;
pNode->GetClassName(wsElement);
CFX_WideString wsName;
XFA_SaveAttribute(pNode, XFA_ATTRIBUTE_Name, FX_WSTRC(L"name"), TRUE,
wsName);
buf << FX_WSTRC(L"<");
buf << wsElement;
buf << wsName;
buf << wsAttrs;
if (wsChildren.IsEmpty()) {
buf << FX_WSTRC(L"\n/>");
} else {
buf << FX_WSTRC(L"\n>");
buf << wsChildren;
buf << FX_WSTRC(L"</");
buf << wsElement;
buf << FX_WSTRC(L"\n>");
}
}
}
static void XFA_DataExporter_RegenerateFormFile_Container(
CXFA_Node* pNode,
IFX_Stream* pStream,
FX_BOOL bSaveXML = FALSE) {
XFA_Element eType = pNode->GetElementType();
if (eType == XFA_Element::Field || eType == XFA_Element::Draw ||
!pNode->IsContainerNode()) {
CFX_WideTextBuf buf;
XFA_DataExporter_RegenerateFormFile_Changed(pNode, buf, bSaveXML);
FX_STRSIZE nLen = buf.GetLength();
if (nLen > 0) {
pStream->WriteString((const FX_WCHAR*)buf.GetBuffer(), nLen);
}
return;
}
CFX_WideStringC wsElement;
pNode->GetClassName(wsElement);
pStream->WriteString(L"<", 1);
pStream->WriteString(wsElement.c_str(), wsElement.GetLength());
CFX_WideString wsOutput;
XFA_SaveAttribute(pNode, XFA_ATTRIBUTE_Name, FX_WSTRC(L"name"), TRUE,
wsOutput);
CFX_WideString wsAttrs;
int32_t iAttrs = 0;
const uint8_t* pAttrs =
XFA_GetElementAttributes(pNode->GetElementType(), iAttrs);
while (iAttrs--) {
const XFA_ATTRIBUTEINFO* pAttr =
XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]);
if (pAttr->eName == XFA_ATTRIBUTE_Name) {
continue;
}
CFX_WideString wsAttr;
XFA_SaveAttribute(pNode, pAttr->eName, pAttr->pName, FALSE, wsAttr);
wsOutput += wsAttr;
}
if (!wsOutput.IsEmpty()) {
pStream->WriteString(wsOutput.c_str(), wsOutput.GetLength());
}
CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
if (pChildNode) {
pStream->WriteString(L"\n>", 2);
while (pChildNode) {
XFA_DataExporter_RegenerateFormFile_Container(pChildNode, pStream,
bSaveXML);
pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
}
pStream->WriteString(L"</", 2);
pStream->WriteString(wsElement.c_str(), wsElement.GetLength());
pStream->WriteString(L"\n>", 2);
} else {
pStream->WriteString(L"\n/>", 3);
}
}
void XFA_DataExporter_RegenerateFormFile(CXFA_Node* pNode,
IFX_Stream* pStream,
const FX_CHAR* pChecksum,
FX_BOOL bSaveXML) {
if (pNode->IsModelNode()) {
static const FX_WCHAR s_pwsTagName[] = L"<form";
static const FX_WCHAR s_pwsClose[] = L"</form\n>";
pStream->WriteString(s_pwsTagName, FXSYS_wcslen(s_pwsTagName));
if (pChecksum) {
static const FX_WCHAR s_pwChecksum[] = L" checksum=\"";
CFX_WideString wsChecksum = CFX_WideString::FromUTF8(pChecksum);
pStream->WriteString(s_pwChecksum, FXSYS_wcslen(s_pwChecksum));
pStream->WriteString(wsChecksum.c_str(), wsChecksum.GetLength());
pStream->WriteString(L"\"", 1);
}
pStream->WriteString(L" xmlns=\"", FXSYS_wcslen(L" xmlns=\""));
const FX_WCHAR* pURI = XFA_GetPacketByIndex(XFA_PACKET_Form)->pURI;
pStream->WriteString(pURI, FXSYS_wcslen(pURI));
CFX_WideString wsVersionNumber;
XFA_DataExporter_RecognizeXFAVersionNumber(
ToNode(pNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Template)),
wsVersionNumber);
if (wsVersionNumber.IsEmpty()) {
wsVersionNumber = FX_WSTRC(L"2.8");
}
wsVersionNumber += FX_WSTRC(L"/\"\n>");
pStream->WriteString(wsVersionNumber.c_str(), wsVersionNumber.GetLength());
CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pChildNode) {
XFA_DataExporter_RegenerateFormFile_Container(pChildNode, pStream);
pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
}
pStream->WriteString(s_pwsClose, FXSYS_wcslen(s_pwsClose));
} else {
XFA_DataExporter_RegenerateFormFile_Container(pNode, pStream, bSaveXML);
}
}
CXFA_DataExporter::CXFA_DataExporter(CXFA_Document* pDocument)
: m_pDocument(pDocument) {
ASSERT(m_pDocument);
}
FX_BOOL CXFA_DataExporter::Export(IFX_FileWrite* pWrite) {
return Export(pWrite, m_pDocument->GetRoot());
}
FX_BOOL CXFA_DataExporter::Export(IFX_FileWrite* pWrite,
CXFA_Node* pNode,
uint32_t dwFlag,
const FX_CHAR* pChecksum) {
if (!pWrite) {
ASSERT(false);
return FALSE;
}
IFX_Stream* pStream = IFX_Stream::CreateStream(
pWrite,
FX_STREAMACCESS_Text | FX_STREAMACCESS_Write | FX_STREAMACCESS_Append);
if (pStream == NULL) {
return FALSE;
}
pStream->SetCodePage(FX_CODEPAGE_UTF8);
FX_BOOL bRet = Export(pStream, pNode, dwFlag, pChecksum);
pStream->Release();
return bRet;
}
FX_BOOL CXFA_DataExporter::Export(IFX_Stream* pStream,
CXFA_Node* pNode,
uint32_t dwFlag,
const FX_CHAR* pChecksum) {
CFDE_XMLDoc* pXMLDoc = m_pDocument->GetParser()->GetXMLDoc();
if (pNode->IsModelNode()) {
switch (pNode->GetPacketID()) {
case XFA_XDPPACKET_XDP: {
static const FX_WCHAR s_pwsPreamble[] =
L"<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\">";
pStream->WriteString(s_pwsPreamble, FXSYS_wcslen(s_pwsPreamble));
for (CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
Export(pStream, pChild, dwFlag, pChecksum);
}
static const FX_WCHAR s_pwsPostamble[] = L"</xdp:xdp\n>";
pStream->WriteString(s_pwsPostamble, FXSYS_wcslen(s_pwsPostamble));
} break;
case XFA_XDPPACKET_Datasets: {
CFDE_XMLElement* pElement =
static_cast<CFDE_XMLElement*>(pNode->GetXMLMappingNode());
if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) {
return FALSE;
}
CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
ASSERT(pDataNode);
XFA_DataExporter_DealWithDataGroupNode(pDataNode);
pXMLDoc->SaveXMLNode(pStream, pElement);
} break;
case XFA_XDPPACKET_Form: {
XFA_DataExporter_RegenerateFormFile(pNode, pStream, pChecksum);
} break;
case XFA_XDPPACKET_Template:
default: {
CFDE_XMLElement* pElement =
static_cast<CFDE_XMLElement*>(pNode->GetXMLMappingNode());
if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) {
return FALSE;
}
pXMLDoc->SaveXMLNode(pStream, pElement);
} break;
}
} else {
CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
CXFA_Node* pExportNode = pNode;
for (CXFA_Node* pChildNode =
pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
pChildNode;
pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
if (pChildNode != pNode) {
pExportNode = pDataNode;
break;
}
}
CFDE_XMLElement* pElement =
static_cast<CFDE_XMLElement*>(pExportNode->GetXMLMappingNode());
if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) {
return FALSE;
}
XFA_DataExporter_DealWithDataGroupNode(pExportNode);
pElement->SetString(L"xmlns:xfa",
L"http://www.xfa.org/schema/xfa-data/1.0/");
pXMLDoc->SaveXMLNode(pStream, pElement);
pElement->RemoveAttribute(L"xmlns:xfa");
}
return TRUE;
}
void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode) {
if (!pDataNode || pDataNode->GetElementType() == XFA_Element::DataValue) {
return;
}
int32_t iChildNum = 0;
for (CXFA_Node* pChildNode = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
pChildNode;
pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
iChildNum++;
XFA_DataExporter_DealWithDataGroupNode(pChildNode);
}
if (pDataNode->GetElementType() == XFA_Element::DataGroup) {
if (iChildNum > 0) {
CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element);
CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode);
if (pXMLElement->HasAttribute(L"xfa:dataNode")) {
pXMLElement->RemoveAttribute(L"xfa:dataNode");
}
} else {
CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element);
static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode",
L"dataGroup");
}
}
}