| // 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/fm2js/xfa_fm2jsapi.h" |
| #include "xfa/fxfa/parser/xfa_docdata.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_script.h" |
| #include "xfa/fxfa/parser/xfa_utils.h" |
| |
| IXFA_PacketImport* IXFA_PacketImport::Create(CXFA_Document* pDocument) { |
| return new CXFA_DataImporter(pDocument); |
| } |
| 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->GetClassID() == 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"&"); |
| break; |
| case '<': |
| textBuf << FX_WSTRC(L"<"); |
| break; |
| case '>': |
| textBuf << FX_WSTRC(L">"); |
| break; |
| case '\'': |
| textBuf << FX_WSTRC(L"'"); |
| break; |
| case '\"': |
| textBuf << FX_WSTRC(L"""); |
| break; |
| default: |
| textBuf.AppendChar(str[i]); |
| } |
| } |
| return textBuf.GetWideString(); |
| } |
| 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"&"); |
| } else if (ch == '<') { |
| textBuf << FX_WSTRC(L"<"); |
| } else if (ch == '>') { |
| textBuf << FX_WSTRC(L">"); |
| } else if (ch == '\'') { |
| textBuf << FX_WSTRC(L"'"); |
| } else if (ch == '\"') { |
| textBuf << FX_WSTRC(L"""); |
| } else if (ch == ' ') { |
| if (i && str.GetAt(i - 1) != ' ') { |
| textBuf.AppendChar(' '); |
| } else { |
| textBuf << FX_WSTRC(L" "); |
| } |
| } else { |
| textBuf.AppendChar(str.GetAt(i)); |
| } |
| } |
| return textBuf.GetWideString(); |
| } |
| 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->GetClassID() != XFA_ELEMENT_Image) { |
| return bSaveInDataModel; |
| } |
| CXFA_Node* pValueNode = pNode->GetNodeItem(XFA_NODEITEM_Parent); |
| if (!pValueNode || pValueNode->GetClassID() != 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; |
| } |
| FXSYS_assert(pContentNode->GetObjectType() == XFA_OBJECTTYPE_ContentNode); |
| CXFA_Node* pParentNode = pContentNode->GetNodeItem(XFA_NODEITEM_Parent); |
| if (!pParentNode || pParentNode->GetClassID() != XFA_ELEMENT_Value) { |
| return TRUE; |
| } |
| CXFA_Node* pGrandParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent); |
| if (!pGrandParentNode || |
| pGrandParentNode->GetObjectType() != XFA_OBJECTTYPE_ContainerNode) { |
| 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.Empty(); |
| 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->GetClassID(), 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->GetClassID() != XFA_ELEMENT_SharpxHTML && |
| pRawValueNode->GetClassID() != XFA_ELEMENT_Sharptext && |
| pRawValueNode->GetClassID() != XFA_ELEMENT_Sharpxml) { |
| pRawValueNode = pRawValueNode->GetNodeItem(XFA_NODEITEM_NextSibling); |
| } |
| if (!pRawValueNode) { |
| break; |
| } |
| CFX_WideString wsContentType; |
| pNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, FALSE); |
| if (pRawValueNode->GetClassID() == XFA_ELEMENT_SharpxHTML && |
| wsContentType.Equal(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( |
| (const FX_CHAR*)pMemStream->GetBuffer(), pMemStream->GetSize()); |
| pTempStream->Release(); |
| pMemStream->Release(); |
| } else if (pRawValueNode->GetClassID() == XFA_ELEMENT_Sharpxml && |
| wsContentType.Equal(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); |
| FXSYS_assert(pParentNode); |
| CXFA_Node* pGrandparentNode = |
| pParentNode->GetNodeItem(XFA_NODEITEM_Parent); |
| FXSYS_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]); |
| buf << FX_WSTRC(L"</value\n>"); |
| } |
| buf << FX_WSTRC(L"</"); |
| buf << bodyTagName; |
| buf << FX_WSTRC(L"\n>"); |
| wsChildren += buf.GetWideString(); |
| 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->GetClassID() == 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.GetWideString(); |
| newBuf.Clear(); |
| pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); |
| } |
| if (!bSaveXML && !wsChildren.IsEmpty() && |
| pNode->GetClassID() == XFA_ELEMENT_Items) { |
| wsChildren.Empty(); |
| bSaveXML = TRUE; |
| CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); |
| while (pChildNode) { |
| XFA_DataExporter_RegenerateFormFile_Changed(pChildNode, newBuf, |
| bSaveXML); |
| wsChildren += newBuf.GetWideString(); |
| newBuf.Clear(); |
| pChildNode = pChildNode->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 eElement = pNode->GetClassID(); |
| if (eElement == XFA_ELEMENT_Field || eElement == 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.GetPtr(), 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->GetClassID(), 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((const FX_WCHAR*)wsOutput, 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.GetPtr(), 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->GetObjectType() == XFA_OBJECTTYPE_ModelNode) { |
| 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, FXSYS_strlen(pChecksum)); |
| pStream->WriteString(s_pwChecksum, FXSYS_wcslen(s_pwChecksum)); |
| pStream->WriteString((const FX_WCHAR*)wsChecksum, 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_XDPPACKET_Template)), |
| wsVersionNumber); |
| if (wsVersionNumber.IsEmpty()) { |
| wsVersionNumber = FX_WSTRC(L"2.8"); |
| } |
| wsVersionNumber += FX_WSTRC(L"/\"\n>"); |
| pStream->WriteString((const FX_WCHAR*)wsVersionNumber, |
| 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); |
| } |
| } |
| IXFA_PacketExport* IXFA_PacketExport::Create(CXFA_Document* pDocument, |
| XFA_DATAFORMAT eFormat) { |
| return new CXFA_DataExporter(pDocument); |
| } |
| 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->GetObjectType() == XFA_OBJECTTYPE_ModelNode) { |
| 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); |
| FXSYS_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(FX_WSTRC(L"xmlns:xfa"), |
| FX_WSTRC(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->GetClassID() == 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->GetClassID() == XFA_ELEMENT_DataGroup) { |
| if (iChildNum > 0) { |
| CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); |
| FXSYS_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(); |
| FXSYS_assert(pXMLNode->GetType() == FDE_XMLNODE_Element); |
| static_cast<CFDE_XMLElement*>(pXMLNode) |
| ->SetString(FX_WSTRC(L"xfa:dataNode"), FX_WSTRC(L"dataGroup")); |
| } |
| } |
| } |