Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我试图将一个XML文件转换为另一个XML文件,根据标记值对数据进行分组_Xml_Sorting_Xslt_Grouping - Fatal编程技术网

我试图将一个XML文件转换为另一个XML文件,根据标记值对数据进行分组

我试图将一个XML文件转换为另一个XML文件,根据标记值对数据进行分组,xml,sorting,xslt,grouping,Xml,Sorting,Xslt,Grouping,我要转换以下XML文件: <?xml version="1.0" encoding="UTF-8"?> <dataroot> <Op> <Where>AIX</Where> <Amount>24</Amount> </Op> <Op> <Where>LILLE</Where> <Amount>10</A

我要转换以下XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<dataroot> 
  <Op>
    <Where>AIX</Where>
    <Amount>24</Amount>
  </Op>
  <Op>
    <Where>LILLE</Where>
    <Amount>10</Amount>
  </Op>
  <Op>
    <Where>LILLE</Where>
    <Amount>18</Amount>
  </Op>
  <Op>
    <Where>AIX</Where>
    <Amount>20</Amount>
  </Op>
  <Op>
    <Where>LILLE</Where>
    <Amount>12</Amount>
   </Op>
</dataroot>

艾克斯
24
里尔
10
里尔
18
艾克斯
20
里尔
12


5.
84
艾克斯
2.
44
24
20
里尔
3.
40
10
18
12
也就是将为给定位置执行的操作分组在一起,计算它们的数量和每个位置的操作总量。我用sort做了一些尝试,但没有成功

我是个新手,我不知道怎么做

根据michael.hor257k建议,我尝试使用以下xsl代码创建分组,但仍然无法计算每个位置的操作计数(Nop)和LocAmount:

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

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

  <xsl:key name="Ops-by-location" match="Op" use="Where" />

  <xsl:template match="/">
    <Document> 
      <Recap>
        <Nop><xsl:value-of select="count(//Amount)"/></Nop>
        <TotAmount><xsl:value-of select="sum(//Amount)"/></TotAmount>
      </Recap>
      <xsl:apply-templates/> 
    </Document>  
  </xsl:template>

  <xsl:template match="/dataroot">
    <xsl:apply-templates select="Op[generate-id(.) = generate-id(key('Ops-by-location', Where)[1])]"/>
  </xsl:template>

  <xsl:template match="Op">
    <Where>
      <xsl:value-of select="Where" />
      <Nop>???</Nop>
      <TotAmount>???</TotAmount>
      <xsl:for-each select="key('Ops-by-location', Where)">
        <Amount> <xsl:value-of select="Amount" /></Amount>
      </xsl:for-each>
    </Where>
  </xsl:template>
</xsl:stylesheet>

???
???
试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input =
               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
               "<dataroot>" +
                 "<Op>" +
                   "<Where>AIX</Where>" +
                   "<Amount>24</Amount>" +
                 "</Op>" +
                 "<Op>" +
                   "<Where>LILLE</Where>" +
                   "<Amount>10</Amount>" +
                 "</Op>" +
                 "<Op>" +
                   "<Where>LILLE</Where>" +
                   "<Amount>18</Amount>" +
                 "</Op>" +
                 "<Op>" +
                   "<Where>AIX</Where>" +
                   "<Amount>20</Amount>" +
                 "</Op>" +
                 "<Op>" +
                   "<Where>LILLE</Where>" +
                   "<Amount>12</Amount>" +
                  "</Op>" +
               "</dataroot>";

            XDocument doc1 = XDocument.Parse(input);
            var groups = doc1.Descendants("Op").GroupBy(x => x.Element("Where").Value).ToList();
            int count = doc1.Descendants("Op").Count();
            int total = doc1.Descendants("Amount").Select(x => (int)x).Sum();

            XDocument doc2 = XDocument.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Document></Document>");
            XElement document = doc2.Element("Document");
            XElement recap = new XElement("Recap");
            document.Add(recap);
            recap.Add(new XElement("Nop", count));
            recap.Add(new XElement("TotAmount", total));

            foreach (var opGroup in groups.AsEnumerable())
            {
                XElement location = new XElement("Location");
                document.Add(location);
                location.Add(opGroup.Elements("Where").FirstOrDefault());
                int groupCount = opGroup.Count();
                int locAmount = opGroup.Descendants("Amount").Select(x => (int)x).Sum();
                location.Add(new XElement("Nop", groupCount));
                location.Add(new XElement("LocAmount", locAmount));

                XElement ops = new XElement("Ops");
                location.Add(ops);
                foreach (var op in opGroup)
                {
                    ops.Add(op.Element("Amount"));
                }

            }


        }
    }
}
​
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用System.Xml.Linq;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串输入=
"" +
"" +
"" +
“AIX”+
"24" +
"" +
"" +
“里尔”+
"10" +
"" +
"" +
“里尔”+
"18" +
"" +
"" +
“AIX”+
"20" +
"" +
"" +
“里尔”+
"12" +
"" +
"";
XDocument doc1=XDocument.Parse(输入);
var groups=doc1.substands(“Op”).GroupBy(x=>x.Element(“Where”).Value).ToList();
int count=doc1.substands(“Op”).count();
int total=doc1.Sum(“金额”).Select(x=>(int)x.Sum();
XDocument doc2=XDocument.Parse(“”);
XElement文档=doc2.元素(“文档”);
XElement重述=新XElement(“重述”);
文件。添加(重述);
添加(新元素(“Nop”,计数));
加上(新项目(“总额”),总计);
foreach(组中的var opGroup.AsEnumerable())
{
XElement位置=新XElement(“位置”);
文件。添加(位置);
Add(opGroup.Elements(“Where”).FirstOrDefault());
int groupCount=opGroup.Count();
int locAmount=opGroup.substands(“Amount”).Select(x=>(int)x.Sum();
添加(新的元素(“Nop”,groupCount));
位置。添加(新元素(“LocAmount”,LocAmount));
XElement ops=新XElement(“ops”);
地点.增补(行动处);
foreach(opGroup中的var op)
{
运营增加(运营要素(“金额”);
}
}
}
}
}
​
我仍然无法计算操作计数(Nop)和LocAmount 对于每个位置

尝试:


或者,更有效一点:

<xsl:template match="Op">
    <xsl:variable name="local-ops" select="key('Ops-by-location', Where)"/>
    <Location>
        <xsl:copy-of select="Where"/>
        <Nop>
            <xsl:value-of select="count($local-ops)"/>
        </Nop>
        <TotAmount>
            <xsl:value-of select="sum($local-ops/Amount)"/>
        </TotAmount>
        <xsl:copy-of select="$local-ops/Amount"/>
    </Location>
</xsl:template>

下面是一个使用Muenchian方法的XSLT 1.0解决方案:

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

<xsl:key name="Where" match="/dataroot/Op/Where" use="text()" />

<xsl:template match="/">
  <xsl:element name="Document">
    <xsl:element name="Recap">
      <xsl:for-each select="//dataroot">
    <Nop><xsl:value-of select="count(*)"/></Nop>
        <TotAmount><xsl:value-of select="sum(//Amount)"/></TotAmount>
      </xsl:for-each>
    </xsl:element>

   <xsl:for-each select="/dataroot/Op/Where[generate-id()
                         = generate-id(key('Where',text())[1])]">
    <xsl:element name="Location">       

      <Where><xsl:value-of select="."/></Where>             
      <Nop><xsl:value-of select="count(key('Where',text()))"/></Nop>
      <LocAmount><xsl:value-of select="sum(key('Where',text())/../Amount)"/></LocAmount>

    <xsl:element name="Ops">
       <xsl:copy-of select="key('Where',text())/../Amount"/>              
    </xsl:element>

    </xsl:element>      
   </xsl:for-each>      

  </xsl:element>  
</xsl:template>

</xsl:stylesheet>


搜索
XSLT
分组
——这可能是这里最常问的问题。请注意,XSLT1.0或2.0的答案不同。这是什么语言?这个问题被标记为XSLT.C#,但也可以在vb.net中完成。使用XML Linq。@Parfait正如我所说的,这个问题被标记为XSLT。我看不出“你的编程伙伴”喜欢什么有什么关系。
<xsl:template match="Op">
    <xsl:variable name="local-ops" select="key('Ops-by-location', Where)"/>
    <Location>
        <xsl:copy-of select="Where"/>
        <Nop>
            <xsl:value-of select="count($local-ops)"/>
        </Nop>
        <TotAmount>
            <xsl:value-of select="sum($local-ops/Amount)"/>
        </TotAmount>
        <xsl:copy-of select="$local-ops/Amount"/>
    </Location>
</xsl:template>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />

<xsl:key name="Where" match="/dataroot/Op/Where" use="text()" />

<xsl:template match="/">
  <xsl:element name="Document">
    <xsl:element name="Recap">
      <xsl:for-each select="//dataroot">
    <Nop><xsl:value-of select="count(*)"/></Nop>
        <TotAmount><xsl:value-of select="sum(//Amount)"/></TotAmount>
      </xsl:for-each>
    </xsl:element>

   <xsl:for-each select="/dataroot/Op/Where[generate-id()
                         = generate-id(key('Where',text())[1])]">
    <xsl:element name="Location">       

      <Where><xsl:value-of select="."/></Where>             
      <Nop><xsl:value-of select="count(key('Where',text()))"/></Nop>
      <LocAmount><xsl:value-of select="sum(key('Where',text())/../Amount)"/></LocAmount>

    <xsl:element name="Ops">
       <xsl:copy-of select="key('Where',text())/../Amount"/>              
    </xsl:element>

    </xsl:element>      
   </xsl:for-each>      

  </xsl:element>  
</xsl:template>

</xsl:stylesheet>