title: XSLT & XPath very complex data transformation
body: <p>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.</p>
  
  <p>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.</p>
  
  <p>Any way, here is a fair example of an INPUT file:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;PackageName TransmissionID="0792d49a-c09b-4094-9f4e-2357a042865c"&gt;
    &lt;Version&gt;1.0&lt;/Version&gt;
    &lt;DateReported&gt;04/12/2010&lt;/DateReported&gt;
    &lt;TimeReported&gt;10:16:46.9385105&lt;/TimeReported&gt;
    &lt;!-- Status=Disposition --&gt;
    &lt;ReportPackage Status="Disposition1"&gt;
      &lt;Addresses&gt;
        &lt;Address&gt;
          &lt;!-- PersonAddress --&gt;
          &lt;Name&gt;Stephen Stipulate&lt;/Name&gt;
          &lt;Address&gt;1200 Any Street&lt;/Address&gt;
          &lt;City&gt;Some City&lt;/City&gt;
          &lt;State&gt;XX&lt;/State&gt;
          &lt;Zip&gt;12345&lt;/Zip&gt;
          &lt;Phone&gt;800-555-1212&lt;/Phone&gt;
        &lt;/Address&gt;
      &lt;/Addresses&gt;
      &lt;Parts packageID="APackageId"&gt;
        &lt;packageClientAccount&gt;00000000&lt;/packageClientAccount&gt;
        &lt;DiscardedIdentifier id="NothingOfInterest"&gt;
          &lt;AssemblyId&gt;
            &lt;IdValue&gt;0547224801-0908&lt;/IdValue&gt;
          &lt;/AssemblyId&gt;
          &lt;!-- Status --&gt;
          &lt;AssemblyStatus&gt;
            &lt;Status&gt;OutOfStock&lt;/Status&gt;
            &lt;DateReOrderReceived&gt;2009-09-24T06:09:00&lt;/DateReOrderReceived&gt;
          &lt;/AssemblyStatus&gt;
          &lt;PartVendor&gt;
            &lt;!-- VendorAddress --&gt;
            &lt;VendorName&gt;Roger Refactor&lt;/VendorName&gt;
            &lt;VendorAddress&gt;
              &lt;IdValue name="Address"&gt;100 An Avenue Suite 13&lt;/IdValue&gt;
              &lt;IdValue name="City"&gt;A Different City&lt;/IdValue&gt;
              &lt;IdValue name="State"&gt;YY&lt;/IdValue&gt;
              &lt;IdValue name="Zip"&gt;54321&lt;/IdValue&gt;
              &lt;IdValue name="Phone"&gt;866-555-1212&lt;/IdValue&gt;
            &lt;/VendorAddress&gt;
          &lt;/PartVendor&gt;
          &lt;PartsMainSegment&gt;
            &lt;AdditionalSegment&gt;
              &lt;PartSpecs&gt;
                &lt;Spec&gt;
                  &lt;PartId&gt;123456&lt;/PartId&gt;
                  &lt;Name&gt;Widget1&lt;/Name&gt;
                  &lt;ThresholdLevel&gt;000500&lt;/ThresholdLevel&gt;
                &lt;/Spec&gt;
                &lt;Spec&gt;
                  &lt;PartId&gt;234567&lt;/PartId&gt;
                  &lt;Name&gt;Widget2&lt;/Name&gt;
                  &lt;ThresholdLevel&gt;000200&lt;/ThresholdLevel&gt;
                &lt;/Spec&gt;
              &lt;/PartSpecs&gt;
            &lt;/AdditionalSegment&gt;
          &lt;/PartsMainSegment&gt;
          &lt;AdditionallPartsSegment&gt;
            &lt;Spec&gt;
              &lt;PartId&gt;123456&lt;/PartId&gt;
              &lt;PartType&gt;ABC&lt;/PartType&gt;
            &lt;/Spec&gt;
            &lt;Spec&gt;
              &lt;PartId&gt;234567&lt;/PartId&gt;
              &lt;PartType&gt;CBA&lt;/PartType&gt;
            &lt;/Spec&gt;
          &lt;/AdditionallPartsSegment&gt;
          &lt;AdditionalItems type="RawData" qualifier="mode" vendor="rogerRefactor"&gt;
            &lt;Text&gt;AModeValue&lt;/Text&gt;
          &lt;/AdditionalItems&gt;
          &lt;AdditionalItems type="RawData" qualifier="indicator" vendor="rogerRefactor"&gt;
            &lt;Text&gt;AnIndicator&lt;/Text&gt;
          &lt;/AdditionalItems&gt;
        &lt;/DiscardedIdentifier&gt;
      &lt;/Parts&gt;
    &lt;/ReportPackage&gt;
  &lt;/PackageName&gt;
  </code></pre>
  
  <p>And the desired OUTPUT file:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;Package&gt;
    &lt;TransmissionID&gt;0792d49a-c09b-4094-9f4e-2357a042865c&lt;/TransmissionID&gt;
    &lt;PackageType&gt;PackageName&lt;/PackageType&gt;
    &lt;Version&gt;1.0&lt;/Version&gt;
    &lt;DateReported&gt;1/03/2011&lt;/DateReported&gt;
    &lt;TimeReported&gt;16:25:35.1293170&lt;/TimeReported&gt;
    &lt;Disposition&gt;Disposition1&lt;/Disposition&gt;&gt;
    &lt;packageID&gt;APackageId&lt;/packageID&gt;
    &lt;packageClientAccount&gt;00000000&lt;/packageClientAccount&gt;
    &lt;Addresses&gt;
      &lt;PersonAddress&gt;
        &lt;Name&gt;Stephen Stipulate&lt;/Name&gt;
        &lt;Address&gt;1200 Any Street&lt;/Address&gt;
        &lt;City&gt;Some City&lt;/City&gt;
        &lt;State&gt;XX&lt;/State&gt;
        &lt;Zip&gt;12345&lt;/Zip&gt;
        &lt;Phone&gt;800-555-1212&lt;/Phone&gt;
      &lt;/PersonAddress&gt;
      &lt;VendorAddress&gt;
        &lt;Name&gt;Roger Refactor&lt;/Name&gt;
        &lt;Address&gt;100 An Avenue Suite 13&lt;/Address&gt;
        &lt;City&gt;A Different City&lt;/City&gt;
        &lt;State&gt;YY&lt;/State&gt;
        &lt;Zip&gt;54321&lt;/Zip&gt;
        &lt;Phone&gt;866-555-1212&lt;/Phone&gt;
      &lt;/VendorAddress&gt;
    &lt;/Addresses&gt;
    &lt;Parts&gt;
      &lt;AssemblyId id="0547224801-0908"&gt;
        &lt;Status&gt;OutOfStock&lt;/Status&gt;
        &lt;DateReOrderReceived&gt;2009-09-24T06:09:00&lt;/DateReOrderReceived&gt;
        &lt;Part&gt;
          &lt;PartId&gt;123456&lt;/PartId&gt;
          &lt;PartName&gt;Widget1&lt;/PartName&gt;
          &lt;Level&gt;000500&lt;/Level&gt;
          &lt;PartType&gt;ABC&lt;/PartType&gt;
        &lt;/Part&gt;
        &lt;Part&gt;
          &lt;PartId&gt;234567&lt;/PartId&gt;
          &lt;PartNameName&gt;Widget2&lt;/PartNameName&gt;
          &lt;Level&gt;000200&lt;/Level&gt;
          &lt;PartType&gt;CBA&lt;/PartType&gt;
        &lt;/Part&gt;
      &lt;/AssemblyId&gt;
    &lt;/Parts&gt;
    &lt;AdditionalData&gt;
      &lt;Vendor&gt;TheVendor&lt;/Vendor&gt;
      &lt;Mode&gt;AModeValue&lt;/Mode&gt;
      &lt;Indicator&gt;AnIndicator&lt;/Indicator&gt;
    &lt;/AdditionalData&gt;
  &lt;/Package&gt;
  </code></pre>
  
  <p>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! :)</p>
  
  <p>Well thanks for any and all help - cheers! :)</p>