Sort complex XML structure by nested attribute usi

2019-08-03 13:21发布

I am looking to sort an XML structure using XSLT using xsltproc:

The xml needs to be sorted from CompanyLocation according to the salesman's standard sales inside Usercontent. My XSLT however never seems to sort the data, only copy it.

Below is one CompanyLocation XML tree structure I have about 400 others.

XML data:

<Company>
<CompanyStats>
    <CompanyLocation="London">
        <OfficeID>1</OfficeID>
        <Totalworkers>20
        <NoCleaners>2
        <TopSales>
            <UserID>4<UserID>
            <Sales>43</Sales>
            <Description> Highest sales this quater</Description>
        </TopSales>
        <LowestSales>
            <UserID>12<UserID>
            <Sales>26</Sales>
            <Description> Lowest sales this quater</Description>
        </LowestSales>
        <UserContent>
            <ID>4
            <FirstName>Jack</FirstName>
            <Surname>Black</Surname>
            <StartDate>11/11/2011</StartDate>
            <StandardSales>
                <SSID>0<SSID>
                <Sales>64</Sales>
                <SalesManager>Steve Hewitt<SalesManager>
            </StandardSales>
            <BusinessSales>
                <BSID>0<BSID>
                <Sales>64</Sales>
                <SalesManager>Steve Hewitt<SalesManager>                    
            </BusinessSales>
        </UserContent>
    </CompanyLocation>
</CompanyStats>

Here is my attached XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="node()|@*">
        <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
        </xsl:copy> 
    </xsl:template>
<xsl:template match="CompanyStats">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="CompanyLocation/UserContent/StandardSales/Sales" order="descending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

As i have about 400 CompanyLocation Trees I wish to have the whole tree for each CompanyLocaiton ordered by sales:

<CompanyLocation="London">
<.....>
    <StandardSales>
      <Sales>4</Sales>
    <StandardSales>
<.....>
</CompanyLocation>
<CompanyLocation="Birmingham">
<.....>
    <StandardSales>
     <Sales>25</Sales>
<StandardSales>
    <.....>
</CompanyLocation>
<CompanyLocation="Norwich">
<.....>
    <StandardSales>
     <Sales>35</Sales>
    <StandardSales>
<.....>
</CompanyLocation>

标签: xml xslt
2条回答
该账号已被封号
2楼-- · 2019-08-03 13:41

Your sort wants to be relative to the node you are selecting. not the context of the template you are in.

try <xsl:sort select="UserContent/StandardSales/Sales" order="descending"/> as you are selecting CompanyLocation.

查看更多
女痞
3楼-- · 2019-08-03 13:43

That is sorting the attributes and children of CompanyStats, but there are no attributes and only one element child (and two white space node) children of that element so all it is doing is bringing the white space before or after the element. I suspect you want to apply the sorting a level down:

<xsl:template match="CompanyLocation">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="*">
            <xsl:sort select="UserContent/StandardSales/Sales" order="descending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

But actually I'm not clear what you do want, perhaps you could edit your question to add the result that you want in this case.

UPDATE even after clarification in comments, you don't make it easy to help:

 <CompanyLocation="London">

not well formed, presumably an attribute name missing?

 <Totalworkers>20

not well formed, missing end tag,

And assorted other errors in the file. I think a corrected input and working stylesheet are below.

<Company>
 <CompanyStats>
  <CompanyLocation id="London">
   <OfficeID>1</OfficeID>
   <Totalworkers>20</Totalworkers>
   <NoCleaners>2</NoCleaners>
   <TopSales>
    <UserID>4</UserID>
    <Sales>43</Sales>
    <Description> Highest sales this quater</Description>
   </TopSales>
   <LowestSales>
    <UserID>12</UserID>
    <Sales>26</Sales>
    <Description> Lowest sales this quater</Description>
   </LowestSales>
   <UserContent>
    <ID>4</ID>
    <FirstName>Jack</FirstName>
    <Surname>Black</Surname>
    <StartDate>11/11/2011</StartDate>
    <StandardSales>
     <SSID>0</SSID>
     <Sales>64</Sales>
     <SalesManager>Steve Hewitt</SalesManager>
    </StandardSales>
    <BusinessSales>
     <BSID>0</BSID>
     <Sales>64</Sales>
     <SalesManager>Steve Hewitt</SalesManager>                    
    </BusinessSales>
   </UserContent>
  </CompanyLocation>
  <CompanyLocation id="Paris">
   <OfficeID>1</OfficeID>
   <Totalworkers>20</Totalworkers>
   <NoCleaners>2</NoCleaners>
   <TopSales>
    <UserID>4</UserID>
    <Sales>43</Sales>
    <Description> Highest sales this quater</Description>
   </TopSales>
   <LowestSales>
    <UserID>12</UserID>
    <Sales>26</Sales>
    <Description> Lowest sales this quater</Description>
   </LowestSales>
   <UserContent>
    <ID>4</ID>
    <FirstName>Jack</FirstName>
    <Surname>Black</Surname>
    <StartDate>11/11/2011</StartDate>
    <StandardSales>
     <SSID>0</SSID>
     <Sales>122</Sales>
     <SalesManager>Steve Hewitt</SalesManager>
    </StandardSales>
    <BusinessSales>
     <BSID>0</BSID>
     <Sales>64</Sales>
     <SalesManager>Steve Hewitt</SalesManager>                    
    </BusinessSales>
   </UserContent>
  </CompanyLocation>
 </CompanyStats>
</Company>

and stylesheet, the main change being the xsl:sort select attribute and datatype="number" to get numeric sorting.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="CompanyStats">
 <xsl:copy>
  <xsl:copy-of select="@*"/>
  <xsl:apply-templates select="CompanyLocation">
   <xsl:sort data-type="number" select="UserContent/StandardSales/Sales" order="descending"/>
  </xsl:apply-templates>
 </xsl:copy>
</xsl:template>

</xsl:stylesheet>
查看更多
登录 后发表回答