Profile picture for user sarke

I have an XML source that puts data at various "parent" levels. If I select the "detail" level, the parent attributes are not represented in the XML data feed. Is there some way to do that?

An example document:

 

<?xml version="1.0" encoding="UTF-8" ?>
<services>
  <service name="V_ShippingInfo" owner="Douglas Kelly" userVer="1.0">
    <consumer consName="Consumer_Shipping">
      <details>
        <totalhits>1</totalhits>
        <successHits>1</successHits>
        <avgRespTime>1441</avgRespTime>
        <requestPayload>66</requestPayload>
        <responsePayload>625</responsePayload>
      </details>
    </consumer>
  </service>
  <service name="V_EmployeeData" owner="Douglas Kelly" userVer="1.0"></service>
  <service name="V_LocationSessionData" owner="INTERNAL\Administrator" userVer="1.0">
    <consumer consName="Consumer_Vendor">
      <details>
        <totalhits>1</totalhits>
        <successHits>1</successHits>
        <avgRespTime>1043</avgRespTime>
        <requestPayload>2258</requestPayload>
        <responsePayload>850</responsePayload>
      </details>
    </consumer>
  </service>
  <service name="V_CrmLocationUpdate" owner="Douglas Kelly" userVer="1.0">
    <consumer consName="Consumer_ESB">
      <details>
        <totalhits>24</totalhits>
        <successHits>0</successHits>
        <avgRespTime></avgRespTime>
        <requestPayload></requestPayload>
        <responsePayload></responsePayload>
      </details>
    </consumer>
    <consumer consName="unknown">
      <details>
        <totalhits>4</totalhits>
        <successHits>0</successHits>
        <avgRespTime></avgRespTime>
        <requestPayload></requestPayload>
        <responsePayload></responsePayload>
      </details>
    </consumer>
  </service>
  <service name="V_CrmLocationDetailsUpdate" owner="Douglas Kelly" userVer="1.0"></service>
  <service name="V_CrmScheduleUpdate" owner="Douglas Kelly" userVer="1.0"></service>
  <service name="V_LocationMaster" owner="Douglas Kelly" userVer="1.1">
    <consumer consName="Consumer_CRM">
      <details>
        <totalhits>250</totalhits>
        <successHits>239</successHits>
        <avgRespTime>810</avgRespTime>
        <requestPayload>2276</requestPayload>
        <responsePayload>4327</responsePayload>
      </details>
    </consumer>
  </service>
</services>
  I have "/services/service/consumer" as the repeat element, which brings in "consName" as a column, but not /service/@name nor /service/@owner. If I make /services/service the repeat element, then when there is more than one /services/service/consumer for a /services/service node, I get totalhits columns and totalhits_0 columns.    Any ideas on how to get @name, @owner, @userVer in as columns, along with the consumer/details?

 

by Helmut Barro
Posted on Wed, 02/22/2012 - 17:36

The repeating element here is not clear - normally you would expect it to be "//service", which gives you all the services as result. If all you are interested in are the services and their attributes, you could use "//service" as repeating element and simply specify that no children of that node should be processed.

 

Of course this throws away a lot of the data contained in the XML, so that's probably not want you want. The problem here is that each repeating element contains 0 to n child elements - and since each repeating element results in a single MashZone table row, the multiple children have to be put somewhere within that row. MashZone does this by creating additional columns and numbering them (that's why you get those "_0" columns). All data is then contained in the row - though not really usable.

Another approach, which is more complex but also more powerful, is to use the "preprocessing" feature of the XML operator. Essentially, you write a XSLT script that transforms your source XML so that it presents its data in a more MashZone-friendly format. The idea is to iterate over the "consumer" elements and enrich them with the information of their parent elements.

The XSLT script required looks complex but is rather simple for your sample. It restructures the XML so that the column names are a bit different, but makes all the information accessible for MashZone (I'm no real XSLT specialist, so there may be a shorter, more elegant version to achieve this).

 

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

  <!-- iterate over the services -->
  <xsl:template match="/">
    <xsl:element name="result">
      <xsl:for-each select="/services">
        <xsl:apply-templates/>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>

   <!-- simply copy all information of the consumers and their details -->
   <xsl:template match="text()|details|totalhits|successHits|avgRespTime|requestPayload|responsePayload">
      <xsl:copy>
         <xsl:apply-templates/>
      </xsl:copy>
   </xsl:template>

   <!-- enrich the consumers with their parents' information -->
   <xsl:template match="consumer">
      <xsl:copy>
         <consName>
            <xsl:value-of select="@consName"/>
         </consName>
         <serviceOwner>
            <xsl:value-of select="../@owner"/>
         </serviceOwner>
        <serviceName>
            <xsl:value-of select="../@name"/>
        </serviceName>
        <serviceUserVer>
            <xsl:value-of select="../@userVer"/>
        </serviceUserVer>
        <xsl:apply-templates/>
      </xsl:copy>
   </xsl:template>

   <!-- add those cases where the service has no consumer -->
   <xsl:template match="service[not(consumer)]">
      <consumer>
         <consName>
         </consName>
         <serviceOwner>
            <xsl:value-of select="@owner"/>
         </serviceOwner>
         <serviceName>
            <xsl:value-of select="@name"/>
         </serviceName>
         <serviceUserVer>
            <xsl:value-of select="@userVer"/>
         </serviceUserVer>
      </consumer>
   </xsl:template>

</xsl:stylesheet>

If you add that XSLT script to the XML operator in the "preprocessing" option, and specify the new repeating element "consumer", the output will look like this:

As you see, nothing is impossible in MashZone...

0
by Douglas Kelly Author
Posted on Wed, 02/22/2012 - 18:48

ok, I was wondering if XSLT was the appropriate approach. (I updated my post - the selection I was using was /services/service/consumer - not /services/service/details). Since I mange the XML source (it is from an XQuery against CentraSite), I could also flatten the structure from there. 

0
by Helmut Barro
Posted on Thu, 02/23/2012 - 08:50

...which is, of course, even better, since it takes a lot of load off MashZone.

0

Featured achievement

Genius
You like to help others solve their problems by answering questions.
Recent Unlocks
  • KF
  • KH
  • RG
  • Profile picture for user Vee_ARIS
  • Profile picture for user smarty
  • PacMan

Leaderboard

|
icon-arrow-down icon-arrow-cerulean-left icon-arrow-cerulean-right icon-arrow-down icon-arrow-left icon-arrow-right icon-arrow icon-back icon-close icon-comments icon-correct-answer icon-tick icon-download icon-facebook icon-flag icon-google-plus icon-hamburger icon-in icon-info icon-instagram icon-login-true icon-login icon-mail-notification icon-mail icon-mortarboard icon-newsletter icon-notification icon-pinterest icon-plus icon-rss icon-search icon-share icon-shield icon-snapchat icon-star icon-tutorials icon-twitter icon-universities icon-videos icon-views icon-whatsapp icon-xing icon-youtube icon-jobs icon-heart icon-heart2 aris-express bpm-glossary help-intro help-design Process_Mining_Icon help-publishing help-administration help-dashboarding help-archive help-risk icon-knowledge icon-question icon-events icon-message icon-more icon-pencil forum-icon icon-lock