Solved

XPATH XSL group by (or extend hierarchy)

Posted on 2013-11-12
7
261 Views
Last Modified: 2013-11-14
Hi - not sure how to describe here exactly what I am trying to do (from a terminology perspective) however I can show before and desired results.

Here is some XML:

<?xml version="1.0" encoding="utf-8" ?>
<Orders>
  <order id="1001">
    <order_id>1001</order_id>
      <customer_name>Acme Unlimited</customer_name>
      <customer_address>123 Maple Street, OH 123112</customer_address>
      <customer_phone>+61(2)9812-1122</customer_phone>
      <orderItems.orderItem_id>9000</orderItems.orderItem_id>
      <orderItems.orderItemName>My First Item</orderItems.orderItemName>
      <orderItems.orderItemType>My first item type</orderItems.orderItemType>
      <orderItems.orderItemQty>5</orderItems.orderItemQty>
   </order>
  <order id="1002">
    <order_id>1002</order_id>
      <customer_name>Smith and Co Pty</customer_name>
      <customer_address>456 Elm Street, OH 123112</customer_address>
      <customer_phone>+61(2)9812-1122</customer_phone>
      <orderItems.orderItem_id>9001</orderItems.orderItem_id>
      <orderItems.orderItemName>My First Item</orderItems.orderItemName>
      <orderItems.orderItemType>My first item type</orderItems.orderItemType>
      <orderItems.orderItemQty>5</orderItems.orderItemQty>
  </order>
  <order id="1002">
    <order_id>1002</order_id>
      <customer_name>Smith and Co Pty</customer_name>
      <customer_address>456 Elm Street, OH 123112</customer_address>
      <customer_phone>+61(2)9812-1122</customer_phone>
      <orderItems.orderItem_id>9002</orderItems.orderItem_id>
      <orderItems.orderItemName>My Second Item</orderItems.orderItemName>
      <orderItems.orderItemType>My second item type</orderItems.orderItemType>
      <orderItems.orderItemQty>4</orderItems.orderItemQty>
  </order>
  <order id="1002">
      <order_id>1002</order_id>
        <customer_name>Smith and Co Pty</customer_name>
        <customer_address>456 Elm Street, OH 123112</customer_address>
        <customer_phone>+61(2)9812-1122</customer_phone>
        <orderItems.orderItem_id>9003</orderItems.orderItem_id>
        <orderItems.orderItemName>My Third Item</orderItems.orderItemName>
        <orderItems.orderItemType>My third item type</orderItems.orderItemType>
        <orderItems.orderItemQty>3</orderItems.orderItemQty>
   </order>
</Orders>

Open in new window


I would like to transform it to a more hierarchal structure, which I assume its something like a group-by. Any ideas?

<Orders>
  <order id="1001">
    <order_id>1001</order_id>
      <customer_name>Acme Unlimited</customer_name>
      <customer_address>123 Maple Street, OH 123112</customer_address>
      <customer_phone>+61(2)9812-1122</customer_phone>
      <orderItems>
        <orderItem id="9000">
          <orderItem_id>9000</orderItem_id>
          <orderItemName>My First Item 01</orderItemName>
          <orderItemType>My first item 01 type</orderItemType>
          <orderItems.orderItemQty>5</orderItems.orderItemQty>
        </orderItem>
      </orderItems>
    </order>

  <order id="1002">
    <order_id>1002</order_id>
      <customer_name>Smith and Co Pty</customer_name>
      <customer_address>456 Elm Street, OH 123112</customer_address>
      <customer_phone>+61(2)9812-1122</customer_phone>
      <orderItems>
        <orderItem id="9001">
          <orderItems.orderItem_id>9001</orderItems.orderItem_id>
          <orderItemName>My First Item 02</orderItemName>
          <orderItemType>My first item 02 type</orderItemType>
          <orderItemQty>5</orderItemQty>
        </orderItem>
        <orderItem id="9002">
          <orderItem_id>9002</orderItem_id>
          <orderItemName>My Second Item 02</orderItemName>
          <orderItemType>My second item 02 type</orderItemType>
          <orderItemQty>4</orderItemQty>
        </orderItem>
        <orderItem id="9003">
          <orderItem_id>9003</orderItem_id>
          <orderItemName>My Third Item 02</orderItemName>
          <orderItemType>My third item 02 type</orderItemType>
          <orderItemQty>3</orderItemQty>
        </orderItem>
      </orderItems>
    </order>
</Orders>

Open in new window



I unfortunately don't have a lot of time to learn xslt so any quick help would be very much appreciated! Deadline looms .... :)

Bonus points if you provide example code on how to apply the transform using C#!!
0
Comment
Question by:designavenue
  • 4
  • 3
7 Comments
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 395 total points
Comment Utility
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    
    <xsl:key name="order" match="order" use="@id"/>
    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>
    
    <xsl:template match="node()">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="Orders">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="order[generate-id() = generate-id(key('order', @id)[1])]"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="order">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()[not(starts-with(name(), 'orderItems.'))]"/>
            <orderItems>
                <xsl:for-each select="key('order', @id)">
                    <orderItem id="{orderItems.orderItem_id}">
                        <xsl:apply-templates select="node()[starts-with(name(), 'orderItems.')]"/>
                    </orderItem>
                </xsl:for-each>
            </orderItems>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

Open in new window

0
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
This technique uses Muenchian grouping explained very well at

http://www.jenitennison.com/xslt/grouping/muenchian.html

For C#, just google, that is what I would do
0
 

Author Closing Comment

by:designavenue
Comment Utility
Thank you ! Works perfectly. Appreciate your help here.

Also how would I modify it to use:

    <order_id>1001</order_id>

instead of

  <order id="1001">

for the matching process??
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
change the key from
   <xsl:key name="order" match="order" use="@id"/>
into
   <xsl:key name="order" match="order" use="order_id"/>

and each use of the key function from
   key('order', @id)
into
   key('order', order_id)
0
 

Author Comment

by:designavenue
Comment Utility
Great thanks!

One final thing which will clear up all of my questions:

What do I do if there is a namespace on a tag. For example:

<Orders xmlns="http://www.whoopie.com/event">

Doesn't work when I apply the stylesheet. Any ideas?
0
 

Author Comment

by:designavenue
Comment Utility
I figured that one out - by declaring the stylesheet like this:

<xsl:stylesheet version="1.0" exclude-result-prefixes="v2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v2="http://www.whoopie.com/event">

Had some fun turning literal matches to elements.

Is there any way to strip out the orderItems. prefix in the resulting last child nodes?
0
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
if there is an xmlns attribute (technically it is not an attribute but a namespace declaration,
your xml elements are in a namespace, meaning they are essentialy different elements than the ones in the stylesheet. Your fix is right

Post me your latest stylesheet and I will remove the orderItems. prefix
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now