0

I am working on something where data is delivered in various XML formats, and although I can figure out most of the pieces of how to parse it, I do not know enough about XSLT and XPath to know where to begin putting together this type of multiple transform, where some data is obviously just looked up, some data is repeating, elements have to be renamed, some data is in attributes and some in values, and templates probably have to be processed in specific order or be called with variables. I don't think there is this type example present here, and if we could get one, it might solve a lot of issues for people.

The goal is to take input from several sources which provide similar data in different forms, translate them to a common XML form, and write only ONE (1) progam processing path, instead of the four (4) that we now have to maintain. Also, the translation should be easy to deserialize.

Any way, here is a fair example of an INPUT file:

<?xml version="1.0" encoding="utf-8"?>
<PackageName TransmissionID="0792d49a-c09b-4094-9f4e-2357a042865c">
  <Version>1.0</Version>
  <DateReported>04/12/2010</DateReported>
  <TimeReported>10:16:46.9385105</TimeReported>
  <!-- Status=Disposition -->
  <ReportPackage Status="Disposition1">
    <Addresses>
      <Address>
        <!-- PersonAddress -->
        <Name>Stephen Stipulate</Name>
        <Address>1200 Any Street</Address>
        <City>Some City</City>
        <State>XX</State>
        <Zip>12345</Zip>
        <Phone>800-555-1212</Phone>
      </Address>
    </Addresses>
    <Parts packageID="APackageId">
      <packageClientAccount>00000000</packageClientAccount>
      <DiscardedIdentifier id="NothingOfInterest">
        <AssemblyId>
          <IdValue>0547224801-0908</IdValue>
        </AssemblyId>
        <!-- Status -->
        <AssemblyStatus>
          <Status>OutOfStock</Status>
          <DateReOrderReceived>2009-09-24T06:09:00</DateReOrderReceived>
        </AssemblyStatus>
        <PartVendor>
          <!-- VendorAddress -->
          <VendorName>Roger Refactor</VendorName>
          <VendorAddress>
            <IdValue name="Address">100 An Avenue Suite 13</IdValue>
            <IdValue name="City">A Different City</IdValue>
            <IdValue name="State">YY</IdValue>
            <IdValue name="Zip">54321</IdValue>
            <IdValue name="Phone">866-555-1212</IdValue>
          </VendorAddress>
        </PartVendor>
        <PartsMainSegment>
          <AdditionalSegment>
            <PartSpecs>
              <Spec>
                <PartId>123456</PartId>
                <Name>Widget1</Name>
                <ThresholdLevel>000500</ThresholdLevel>
              </Spec>
              <Spec>
                <PartId>234567</PartId>
                <Name>Widget2</Name>
                <ThresholdLevel>000200</ThresholdLevel>
              </Spec>
            </PartSpecs>
          </AdditionalSegment>
        </PartsMainSegment>
        <AdditionallPartsSegment>
          <Spec>
            <PartId>123456</PartId>
            <PartType>ABC</PartType>
          </Spec>
          <Spec>
            <PartId>234567</PartId>
            <PartType>CBA</PartType>
          </Spec>
        </AdditionallPartsSegment>
        <AdditionalItems type="RawData" qualifier="mode" vendor="rogerRefactor">
          <Text>AModeValue</Text>
        </AdditionalItems>
        <AdditionalItems type="RawData" qualifier="indicator" vendor="rogerRefactor">
          <Text>AnIndicator</Text>
        </AdditionalItems>
      </DiscardedIdentifier>
    </Parts>
  </ReportPackage>
</PackageName>

And the desired OUTPUT file:

<?xml version="1.0" encoding="utf-8"?>
<Package>
  <TransmissionID>0792d49a-c09b-4094-9f4e-2357a042865c</TransmissionID>
  <PackageType>PackageName</PackageType>
  <Version>1.0</Version>
  <DateReported>1/03/2011</DateReported>
  <TimeReported>16:25:35.1293170</TimeReported>
  <Disposition>Disposition1</Disposition>>
  <packageID>APackageId</packageID>
  <packageClientAccount>00000000</packageClientAccount>
  <Addresses>
    <PersonAddress>
      <Name>Stephen Stipulate</Name>
      <Address>1200 Any Street</Address>
      <City>Some City</City>
      <State>XX</State>
      <Zip>12345</Zip>
      <Phone>800-555-1212</Phone>
    </PersonAddress>
    <VendorAddress>
      <Name>Roger Refactor</Name>
      <Address>100 An Avenue Suite 13</Address>
      <City>A Different City</City>
      <State>YY</State>
      <Zip>54321</Zip>
      <Phone>866-555-1212</Phone>
    </VendorAddress>
  </Addresses>
  <Parts>
    <AssemblyId id="0547224801-0908">
      <Status>OutOfStock</Status>
      <DateReOrderReceived>2009-09-24T06:09:00</DateReOrderReceived>
      <Part>
        <PartId>123456</PartId>
        <PartName>Widget1</PartName>
        <Level>000500</Level>
        <PartType>ABC</PartType>
      </Part>
      <Part>
        <PartId>234567</PartId>
        <PartNameName>Widget2</PartNameName>
        <Level>000200</Level>
        <PartType>CBA</PartType>
      </Part>
    </AssemblyId>
  </Parts>
  <AdditionalData>
    <Vendor>TheVendor</Vendor>
    <Mode>AModeValue</Mode>
    <Indicator>AnIndicator</Indicator>
  </AdditionalData>
</Package>

We actually get XML similar to this reporting to a web service. Notice the required re-names, movement of data to different parts of the tree, and also in particular the different segments which have to be joined to make a list of part records, which do not have a parent/child relation. I am not offering any bad starting attempt, as I am at a loss as to where to start on this since I simply don't understand how to sequence the processing, and I am certain that somebody out there (Dimitre!), while not on purpose, would make me look like an idiot! :)

Well thanks for any and all help - cheers! :)

4

1 回答 1

2

像这样的东西非常简单,主要是编写一个模板并使用 XPath 选择器从 XML 树中提取信息。

目前尚不清楚某些项目是否可以多次出现 -VendorAddress例如 - 但这种转换至少会根据您提供的输入创建您需要的输出。

有一个问题Package/AdditionalData/Vendor,正如您所说,您想要一个 的值,TheVendor但此字符串未出现在源数据中。我已经从PartVendor/VendorName. 也没有任何东西可以将该名称与 的vendor="rogerRefactor"属性联系起来AdditionalItems,但我相信你会得到这些东西的排序。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/PackageName">
        <Package>
            <TransmissionID><xsl:value-of select="@TransmissionID"/></TransmissionID>
            <PackageType>PackageName</PackageType>
            <xsl:copy-of select="Version"/>
            <xsl:copy-of select="DateReported"/>
            <xsl:copy-of select="TimeReported"/>
            <Disposition><xsl:value-of select="ReportPackage/@Status"/></Disposition>
            <packageID><xsl:value-of select="ReportPackage/Parts/@packageID"/></packageID>
            <packageClientAccount><xsl:value-of select="ReportPackage/Parts/packageClientAccount"/></packageClientAccount>
            <Addresses>
                <PersonAddress>
                    <xsl:apply-templates select="ReportPackage/Addresses/Address"/>
                </PersonAddress>
                <VendorAddress>
                    <xsl:apply-templates select="ReportPackage/Parts//PartVendor"/>
                </VendorAddress>
            </Addresses>
            <xsl:apply-templates select="ReportPackage/Parts"/>
            <AdditionalData>
                <Vendor><xsl:value-of select=".//PartVendor/VendorName"/></Vendor>
                <Mode><xsl:value-of select=".//AdditionalItems[@qualifier='mode']/Text"/></Mode>
                <Indicator><xsl:value-of select=".//AdditionalItems[@qualifier='indicator']/Text"/></Indicator>
            </AdditionalData>
        </Package>
    </xsl:template>

    <xsl:template match="Parts">
        <Parts>
            <AssemblyId>
                <xsl:attribute name="id">
                    <xsl:value-of select=".//AssemblyId/IdValue"/>
                </xsl:attribute>
                <Status><xsl:value-of select=".//AssemblyStatus/Status"/></Status>
                <DateReOrderReceived><xsl:value-of select=".//AssemblyStatus/DateReOrderReceived"/></DateReOrderReceived>
                <xsl:for-each select=".//PartsMainSegment/AdditionalSegment/PartSpecs/Spec">
                    <Part>
                        <xsl:variable name="part-id" select="PartId"/>
                        <PartId><xsl:value-of select="PartId"/></PartId>
                        <PartName><xsl:value-of select="Name"/></PartName>
                        <Level><xsl:value-of select="ThresholdLevel"/></Level>
                        <PartType><xsl:value-of select="//AdditionallPartsSegment/Spec[PartId = $part-id]/PartType"/></PartType>
                    </Part>
                </xsl:for-each>
            </AssemblyId>
        </Parts>
    </xsl:template>

    <xsl:template match="Address">
        <Name><xsl:value-of select="Name"/></Name>
        <Address><xsl:value-of select="Address"/></Address>
        <City><xsl:value-of select="City"/></City>
        <State><xsl:value-of select="State"/></State>
        <Zip><xsl:value-of select="Zip"/></Zip>
        <Phone><xsl:value-of select="Phone"/></Phone>
    </xsl:template>

    <xsl:template match="PartVendor">
        <Name><xsl:value-of select="VendorName"/></Name>
        <Address><xsl:value-of select="VendorAddress/IdValue[@name='Address']"/></Address>
        <City><xsl:value-of select="VendorAddress/IdValue[@name='City']"/></City>
        <State><xsl:value-of select="VendorAddress/IdValue[@name='State']"/></State>
        <Zip><xsl:value-of select="VendorAddress/IdValue[@name='Zip']"/></Zip>
        <Phone><xsl:value-of select="VendorAddress/IdValue[@name='Phone']"/></Phone>
    </xsl:template>

</xsl:stylesheet>

输出

<?xml version="1.0" encoding="UTF-8"?>
<Package>
   <TransmissionID>0792d49a-c09b-4094-9f4e-2357a042865c</TransmissionID>
   <PackageType>PackageName</PackageType>
   <Version>1.0</Version>
   <DateReported>04/12/2010</DateReported>
   <TimeReported>10:16:46.9385105</TimeReported>
   <Disposition>Disposition1</Disposition>
   <packageID>APackageId</packageID>
   <packageClientAccount>00000000</packageClientAccount>
   <Addresses>
      <PersonAddress>
         <Name>Stephen Stipulate</Name>
         <Address>1200 Any Street</Address>
         <City>Some City</City>
         <State>XX</State>
         <Zip>12345</Zip>
         <Phone>800-555-1212</Phone>
      </PersonAddress>
      <VendorAddress>
         <Name>Roger Refactor</Name>
         <Address>100 An Avenue Suite 13</Address>
         <City>A Different City</City>
         <State>YY</State>
         <Zip>54321</Zip>
         <Phone>866-555-1212</Phone>
      </VendorAddress>
   </Addresses>
   <Parts>
      <AssemblyId id="0547224801-0908">
         <Status>OutOfStock</Status>
         <DateReOrderReceived>2009-09-24T06:09:00</DateReOrderReceived>
         <Part>
            <PartId>123456</PartId>
            <PartName>Widget1</PartName>
            <Level>000500</Level>
            <PartType>ABC</PartType>
         </Part>
         <Part>
            <PartId>234567</PartId>
            <PartName>Widget2</PartName>
            <Level>000200</Level>
            <PartType>CBA</PartType>
         </Part>
      </AssemblyId>
   </Parts>
   <AdditionalData>
      <Vendor>Roger Refactor</Vendor>
      <Mode>AModeValue</Mode>
      <Indicator>AnIndicator</Indicator>
   </AdditionalData>
</Package>
于 2013-04-11T21:26:27.183 回答