简体   繁体   English

XSLT之后如何将XML数据保存在一起? (在MS-Access中)

[英]How can I keep XML data together after an XSLT? (In MS-Access)

I'm trying to parse XML data that comes to me as attribute-centric, into an element-centric style using an XSL Transformation. 我正在尝试使用XSL转换将以属性为中心的XML数据解析为以元素为中心的样式。 My goal is to be able to import it into an access database. 我的目标是能够将其导入到访问数据库中。 I've succeeded in parsing it into elements, but my issue now resides in the data being split into multiple tables. 我已经成功地将其解析为元素,但是现在的问题在于将数据拆分为多个表。 I've got multiple categories of element tags, but after the parse when the xsl creates 'blank' header tags for sections, access splits into a new table when it hits the blank tag. 我有多种类别的元素标签,但是在xsl为各节创建“空白”标题标签后进行解析之后,访问权在命中空白标签时会拆分为一个新表。 The structure is (simply) 结构是(简单地)

MeterReadings(with small description attributes) MeterReadings(具有小描述属性)

MetersRead(with small description attributes) MetersRead(具有小的描述属性)

Meter(with the majority of description attributes I need) 仪表(具有我需要的大多数描述属性)

Status(with small description attributes) 状态(带有小的描述属性)

What happens is the XSL creates all of the attributes into elements but then leaves the headers (MeterReadings,MetersRead,Meter,Status) as blank elements. XSL发生的事情是将所有属性创建到元素中,然后将标头(MeterReadings,MetersRead,Meter,Status)留为空白元素。 This causes access to separate these 4 into separate tables, which ends up almost creating useless data as the majority of data in 'Meter' requires the identifiers from the 'MeterReadings' and so on. 这导致将这4个表分离为单独的表的访问,最终几乎创建了无用的数据,因为“仪表”中的大多数数据都需要“仪表读数”中的标识符,依此类推。

I'm a student programmer on placement and brand new to XML/XSLT. 我是一名实习生,是XML / XSLT的新手。 Currently my XSL looks like this 目前我的XSL看起来像这样

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

  <xsl:template match="@*">
    <xsl:element name="{name()}">
    <xsl:value-of select="."/></xsl:element>
  </xsl:template>
</xsl:stylesheet>

This is how my XML looks after transformation, I have around 150k lines of data before the transformation so you can't see MeterReadings in this snip, because it would have to encompass around 1700 lines to see it encapsulated. 这就是我的XML转换后的样子,转换之前我大约有15万行数据,因此您无法在此代码段中看到MeterReadings,因为它必须包含大约1700行才能被封装。

<MetersRead>
<Meter>
<MeterIrn>(Dummy Data)</MeterIrn>
<MeterName>(Dummy Data)</MeterName>
<IsActive>(Dummy Data)</IsActive>
<SerialNumber>(Dummy Data)</SerialNumber>
<MeterType>(Dummy Data)</MeterType>
<Description></Description>
<InstallDate>(Dummy Data)</InstallDate>
<RemovalDate></RemovalDate>
<AccountIdent></AccountIdent>
<AccountName></AccountName>
<SdpIdent>(Dummy Data)</SdpIdent>
<Location>(Dummy Data)</Location>
<TimeZoneIndex>(Dummy Data)</TimeZoneIndex>
<Timezone>(Dummy Data)</Timezone>
<TimeZoneOffset>(Dummy Data)</TimeZoneOffset>
<ObservesDaylightSavings>(Dummy Data)</ObservesDaylightSavings>
<MediaType>(Dummy Data)</MediaType>
<Status>
<Code>(Dummy Data)</Code>
<Text>(Dummy Data)</Text>
</Status>
</Meter>

So hopefully you can see what I mean here, where MetersRead / Meter / Status are open blank tags, this is where MS-Access will split a new table, and anything up until the next blank open tag will go into its own table. 因此,希望您能明白我的意思,在这里MetersRead / Meter / Status是打开的空白标签,这是MS-Access拆分新表的地方,直到下一个空白的打开标签将进入其自己的表。 Any tips are extremely appreciated, I've spent the last few days delving through questions on here, MSDN help, and other resources. 非常感谢任何提示,我花了几天的时间来研究有关此处的问题,MSDN帮助和其他资源。 I've learned a lot from @Lingamurthy CS on here. 我在这里从@Lingamurthy CS学到了很多东西。

Also this is what my XML looks like BEFORE transformation if that helps explain my case 这也是我的XML在转换之前的样子,如果这有助于解释我的情况

<MetersRead >

    <Meter MeterIrn="(Dummy Data)" MeterName="(Dummy Data)" IsActive="(Dummy Data)" SerialNumber="(Dummy Data)" MeterType="(Dummy Data)" Description="" InstallDate="(Dummy Data)" RemovalDate="" AccountIdent="" AccountName="" SdpIdent="(Dummy Data)" Location="(Dummy Data)" TimeZoneIndex="(Dummy Data)" Timezone="(Dummy Data)" TimeZoneOffset="(Dummy Data)" ObservesDaylightSavings="(Dummy Data)" MediaType="(Dummy Data)" >

        <Status Code="(Dummy Data)" Text="(Dummy Data)" />

    </Meter>

Access Table Format The image shows how Access import formats my tables, and you can see that it is splitting the 4 highlighted tables whereas the data is only useful if it stays together in say 1 generic "Meter" table. Access表格式该图显示了Access导入如何格式化我的表,并且您可以看到它正在拆分4个突出显示的表,而仅当数据在1个通用“ Meter”表中在一起时,该数据才有用。 I tried moving fields over to one table such that when the import happens and I only append data to existing fields it would populate it how I needed, but it only fills the tables it can fully identify as the same structure from the XML. 我尝试将字段移到一个表上,以便在导入时仅将数据追加到现有字段中,即可按需要填充它,但仅填充可以完全标识为XML中相同结构的表。

You seem not to be certain exactly what you want. 您似乎不确定自己想要什么。 As best I can interpret your data and request, I think you want each <Meter> element to correspond to one row in one flat table. 尽我所能解释您的数据和请求,我认为您希望每个<Meter>元素都对应一个平面表中的一行。 <MetersRead> is just a collection of the <Meter> elements, so it corresponds to that same table, not a separate one of its own, and <Status> elements are to be flattened into the data for their containing <Meter> . <MetersRead>只是<Meter>元素的集合,因此它对应于同一张表,而不是其自己的单独表,并且<Status>元素将被平整到其包含<Meter>的数据中。 How any of that relates to a MeterReadings element is unclear and cannot be addressed based on the information provided. 目前尚不清楚其中任何一个与MeterReadings元素的关系,因此无法根据提供的信息进行解决。

The main thing to understand about the "blank" open tags -- ie the ones that correspond to elements, rather than attributes, of the input document -- is that they arise from the <xsl:copy> in your stylesheet's identity transform. 关于“空白”打开标记(即与输入文档的元素而不是属性相对应的那些标记)的主要理解是,它们来自样式表的标识转换中的<xsl:copy> The key to omitting them is to apply a different transform to elements that should not have corresponding elements in the output tree. 省略它们的关键是对输出树中不应该具有相应元素的元素应用不同的变换。 You can easily transform an element without copying the element itself. 您可以轻松地变换元素,而无需复制元素本身。

Something along these lines is probably closer to what you want: 这些方面可能更接近您想要的:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- BY DEFAULT, elements and text nodes are copied,
       and elements' attributes and contents are transformed as child nodes
       of the output element -->
  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- By default, attributes are transformed to elements -->
  <xsl:template match="@*">
    <xsl:element name="{name()}">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <!-- Certain elements have only their contents transformed -->
  <xsl:template match="MetersRead | Status">
    <!-- no xsl:copy, and attribute children, if any, are ignored -->
    <xsl:apply-templates select="node()"/>
  </xsl:template>

</xsl:stylesheet>

I had to patch up your example input by closing the <MetersRead> element; 我必须通过关闭<MetersRead>元素来修补示例输入。 the result of applying the above transformation to the result is 将上述变换应用于结果的结果是

<?xml version="1.0"?>
<Meter>
  <MeterIrn>(Dummy Data)</MeterIrn>
  <MeterName>(Dummy Data)</MeterName>
  <IsActive>(Dummy Data)</IsActive>
  <SerialNumber>(Dummy Data)</SerialNumber>
  <MeterType>(Dummy Data)</MeterType>
  <Description/>
  <InstallDate>(Dummy Data)</InstallDate>
  <RemovalDate/>
  <AccountIdent/>
  <AccountName/>
  <SdpIdent>(Dummy Data)</SdpIdent>
  <Location>(Dummy Data)</Location>
  <TimeZoneIndex>(Dummy Data)</TimeZoneIndex>
  <Timezone>(Dummy Data)</Timezone>
  <TimeZoneOffset>(Dummy Data)</TimeZoneOffset>
  <ObservesDaylightSavings>(Dummy Data)</ObservesDaylightSavings>
  <MediaType>(Dummy Data)</MediaType>
  <Code>(Dummy Data)</Code>
  <Text>(Dummy Data)</Text>
</Meter>

Note the absence of any <MetersRead> element and the flattening of the erstwhile <Status> into the host <Meter> . 请注意,没有任何<MetersRead>元素,并且以前的<Status>到主机<Meter>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM