我有一个XML文件,我需要将其导入到Access表中。 XML文件包含带有多个字段的Header,以及带有CDATA字段的报表主体,其中CDATA字段包含重复信息(CDATA中的定界文本)。这是外观的基本版本:
<?xml version="1.0" encoding="UTF-8"?>
<CMCFReport
xsi:noNameSpaceSchemaLocation="CMCReports.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<HEADER>
<ModeS>A5A1ED</ModeS>
<TailNumber>UNKNOWN</TailNumber>
<Timestamp>
<Day>1</Day>
<Month>12</Month>
<Year>2016</Year>
<Hour>18</Hour>
<Minute>36</Minute>
<Second>58</Second>
</Timestamp>
</HEADER>
<ReportBody>
<StorageReport>
<![CDATA[PLF 01DEC16 1835 --------- L
COL3A-0072-001N BCG3F-CMCM-002K
MSG 2158513 01DEC16 1714 TO A 1
FDE 21500944 01DEC16 1713 TA A
FDE 21502445 01DEC16 1713 TA A
MSG 2158512 01DEC16 1714 TO A 1
EOR
]]>
</StorageReport>
</ReportBody>
</CMCFReport>
当我运行导入实用程序时,Access尝试将HEADER数据和REPORT正文数据放入单独的表中。指定每个项目进入哪个字段的用于导入XML的VBA脚本是什么?这是我到目前为止所了解的:
Private Sub btn_Import_Click()
Dim StrFileName As String
Dim fd As FileDialog
Dim vrtSelectedItem As Variant
Dim oDoc As MSXML2.DOMDocument60
Set oDoc = New MSXML2.DOMDocument60
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd.InitialFileName = "c:\sample\*.xml"
If .Show = -1 Then
For Each vrtSelectedItem In .SelectedItems
If oDoc.Load(vrtSelectedItem) Then
Dim oNodes As MSXML2.IXMLDOMNodeList
oNodes = oDoc.Nodes
Dim oNode As MSXML2.IXMLDOMNode
For Each oNode In oNodes
'This is where I imagine the code would be to pull the relevant data out of each node and assign it to a field, I just don't know how to do that`
Next oNode
End If
Next vrtSelectedItem
Else
End If
End With
Set fd = Nothing
End Sub
我以前从未导入过XML,也没有选择重组此XML的选项,因为我会从外部来源接收文件并定期将其导入。任何帮助,将不胜感激。谢谢。
答案 0 :(得分:1)
我无法选择重组此XML ...实际上,您可以使用XSLT(一种用于转换XML文件的专用语言,MSXML运行XSLT 1.0脚本。
只需将 HEADER 和 ReportBody 组合到一个节点中,例如 REPORT (将成为Access表的名称)。然后使用Access'Application.ImportXML导入此转换后的XML。
XSLT (另存为.xsl文件,一个特殊的.xml文件)
private bool dragging;
private string CurrentTool;
private ButtonController[] DrawingTools;
public Camera TheCamera;
public Vector3 MouseStart;
public Vector3 CameraStart;
public float sensitivity;
// Use this for initialization
void Start () {
TheCamera = FindObjectOfType<Camera>();
DrawingTools = FindObjectsOfType<ButtonController>();
}
// Update is called once per frame
void Update () {
for (int i = 0; i < DrawingTools.Length; i++)
{
if (DrawingTools[i].Pressed)
{
CurrentTool = DrawingTools[i].gameObject.name;
}
}
if (dragging && CurrentTool == "PanTool Button")
{
float xChange;
float yChange;
Vector3 MousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (MousePosition.x > MouseStart.x)
{
xChange = -Mathf.Abs(MousePosition.x - MouseStart.x);
}
else
{
xChange = Mathf.Abs(MousePosition.x - MouseStart.x);
}
if (MousePosition.y > MouseStart.y)
{
yChange = -Mathf.Abs(MousePosition.y - MouseStart.y);
}
else
{
yChange = Mathf.Abs(MousePosition.y - MouseStart.y);
}
TheCamera.transform.position = new Vector3(CameraStart.x + xChange*sensitivity, CameraStart.y + yChange*sensitivity, CameraStart.z);
}
}
public void OnPointerDown(PointerEventData EventData)
{
if (!dragging)
{
dragging = true;
MouseStart = new Vector3(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y, 0f);
CameraStart = TheCamera.transform.position;
}
}
public void OnPointerUp(PointerEventData EventData)
{
if (dragging)
{
dragging = false;
}
}
XSLT Fiddle Demo (请参见左下方的结果)
VBA (分离文件选择器的迭代和转换过程,假定所有XML都是相同的结构)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNameSpaceSchemaLocation="CMCReports.xsd"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<data>
<xsl:apply-templates select="HEADER"/>
</data>
</xsl:template>
<xsl:template match="HEADER|ReportBody">
<REPORT>
<xsl:copy-of select="ModeS|TailNumber"/>
<xsl:copy-of select="Timestamp/*"/>
<xsl:copy-of select="following-sibling::ReportBody/*"/>
</REPORT>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
虽然Zack有一个要点(如果您想让我们真正帮助您,您需要分享更多一点),但我可以尝试进一步帮助您。
首先,如果要在没有xsd的情况下解析该XML文档,则需要打开ValidateOnParse
。
然后,您可以使用以下XPATH查询遍历包含实际文本的所有文本节点:
//*[string-length(normalize-space(text())) > 0]/text()
您仍然必须填写有关如何存储它的细节,但这应该可以帮助您入门。它为您提供每个包含文本的节点的节点名称和值。
您仍然必须添加一些逻辑,以将它们存储在表的适当字段中。
Public Sub btn_Import_Click()
Dim StrFileName As String
Dim fd As FileDialog
Dim vrtSelectedItem As Variant
Dim oDoc As MSXML2.DOMDocument60
Set oDoc = New MSXML2.DOMDocument60
oDoc.async = False
oDoc.validateOnParse = True
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.InitialFileName = "c:\sample\*.xml"
If .Show = -1 Then
For Each vrtSelectedItem In .selectedItems
If oDoc.Load(vrtSelectedItem) Then
Dim textNodes As IXMLDOMNodeList
Set textNodes = oDoc.SelectNodes("//*[string-length(normalize-space(text())) > 0]/text()")
Dim l As Long
For l = 0 To textNodes.length - 1
Debug.Print textNodes(l).ParentNode.nodeName 'Node name
Debug.Print textNodes(l).NodeValue 'Node value
Next
End If
Next vrtSelectedItem
Else
End If
End With
Set fd = Nothing
End Sub