使用字段名称对XML记录进行分组使用XSL

时间:2018-03-26 22:15:19

标签: xml xslt xslt-2.0

我正在尝试从此XML中选择值并生成分组的XML输出。 这是XML文件:我正在尝试使用name属性获取单个字段值:select =“field [@ name ='EmployeeEmployeeID']” ** 已编辑添加分数字段 **

<?xml version="1.0" encoding="UTF-8"?>
<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07" xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <record>
    <field name="EmployeeEmployeeID">1234</field>
    <field name="EmployeeFirstName">John</field>
    <field name="EmployeeInitial">A</field>
    <field name="EmployeeLastName">Doe</field>
    <field name="EmployeeTitle">Title</field>
    <field name="ReviewRequest">2017 Review</field>
    <field name="Goal">Goal Title1A</field>
    <field name="Score">3</field>
  </record>
  <record>
    <field name="EmployeeEmployeeID">1234</field>
    <field name="EmployeeFirstName">John</field>
    <field name="EmployeeInitial">A</field>
    <field name="EmployeeLastName">Doe</field>
    <field name="EmployeeTitle">Title</field>
    <field name="ReviewRequest">2017 Review</field>
    <field name="Goal">Goal Title2A</field>
    <field name="Score">2</field>
  </record>
  <record>
    <field name="EmployeeEmployeeID">1234</field>
    <field name="EmployeeFirstName">John</field>
    <field name="EmployeeInitial">A</field>
    <field name="EmployeeLastName">Doe</field>
    <field name="EmployeeTitle">Title</field>
    <field name="ReviewRequest">2018 Review</field>
    <field name="Goal">Goal Title1B</field>
    <field name="Score">2</field>
  </record>
  <record>
    <field name="EmployeeEmployeeID">1234</field>
    <field name="EmployeeFirstName">John</field>
    <field name="EmployeeInitial">A</field>
    <field name="EmployeeLastName">Doe</field>
    <field name="EmployeeTitle">Title</field>
    <field name="ReviewRequest">2018 Review</field>
    <field name="Goal">Goal Title2B</field>
    <field name="Score">3</field>
  </record>
</ExportXML>

我正在尝试获取此输出: ** 已编辑以添加分数字段和部分 **

<?xml version="1.0" encoding="UTF-8"?>
<Reviews>
   <ReviewRequest>
     <EEID>1234</EEID>
     <EEFirstName>John</EEFirstName>
     <EEInitial>A</EEInitial>
     <EELastName>Doe</EELastName>
     <EETitle>Title</EETitle>
     <ReviewRequest>2017 Review</ReviewRequest>
     <Goals>
       <Goal>
         <Goal>Goal Title1A</Goal>
         <Score>3</Score>
       </Goal>
       <Goal>
         <Goal>Goal Title1A</Goal>
         <Score>2</Score>
       </Goal>
     </Goals>
  </ReviewRequest>
  <ReviewRequest>
     <EEID>1234</EEID>
     <EEFirstName>John</EEFirstName>
     <EEInitial>A</EEInitial>
     <EELastName>Doe</EELastName>
     <EETitle>Title</EETitle>
     <ReviewRequest>2018 Review</ReviewRequest>
     <Goals>
       <Goal>
         <Goal>Goal Title1B</Goal>
         <Score>2</Score>
       </Goal>
       <Goal>
         <Goal>Goal Title1B</Goal>
         <Score>3</Score>
       </Goal>
     </Goals>
  </ReviewRequest>
</Reviews>

我尝试使用以下XSL,但我似乎没有使用正确的选择器或正确的分组。任何帮助将不胜感激。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:fct="http://www.taleo.com/xsl_functions" xmlns:e="http://www.taleo.com/ws/tee800/2009/01" xmlns:itk="http://www.taleo.com/ws/integration/toolkit/2005/07" xmlns:so="http://www.taleo.com/ws/so750/2006/12" exclude-result-prefixes="#all">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="/ExportXML">
        <xsl:for-each-group select="./record" group-by="field[@name='ReviewRequest']">
            <xsl:variable name="EEID" select="field[@name='EmployeeEmployeeID']"/>
            <xsl:variable name="EEFirstName" select="field[@name='EmployeeFirstName']"/>
            <xsl:variable name="EEInitial" select="field[@name='EmployeeInitial']"/>
            <xsl:variable name="EELastName" select="field[@name='EmployeeLastName']"/>
            <xsl:variable name="EETitle" select="field[@name='EmployeeTitle']"/>
            <xsl:variable name="ReviewRequest" select="field[@name='ReviewRequest']"/>

            <ReviewRequest>
                <xsl:element name="EEID">
                    <xsl:value-of select="EEID"/>
                </xsl:element>
                <xsl:element name="EEFirstName">
                    <xsl:value-of select="EEFirstName"/>
                </xsl:element>
                <xsl:element name="EEInitial">
                    <xsl:value-of select="EEInitial"/>
                </xsl:element>
                <xsl:element name="EELastName">
                    <xsl:value-of select="EELastName"/>
                </xsl:element>
                <xsl:element name="EETitle">
                    <xsl:value-of select="EETitle"/>
                </xsl:element>
                <xsl:element name="ReviewRequest">
                    <xsl:value-of select="ReviewRequest"/>
                </xsl:element>
                <xsl:element name="Goal">
                    <xsl:for-each-group select="" group-by="field[@name='ReviewRequest']">
                        <xsl:element name="Goals">
                            <xsl:element name="Name">
                                <xsl:variable name="Goal" select="field[@name='Goal']"/>
                                <xsl:value-of select="Goal"/>
                            </xsl:element>
                        </xsl:element>
                        <xsl:value-of select="Goals"/>
                    </xsl:for-each-group>
                </xsl:element>
            </ReviewRequest>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

当前的xsl只输出没有标签的值而没有分组...

    1234
    John
    A
    Doe
    Title
    2017 Review
    Goal Title1A


    1234
    John
    A
    Doe
    Title
    2017 Review
    Goal Title2A


    1234
    John
    A
    Doe
    Title
    2018 Review
    Goal Title1B


    1234
    John
    A
    Doe
    Title
    2018 Review
    Goal Title2B

我从下面的建议开始,结果如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/ExportXML">
    <Reviews>    
      <xsl:for-each-group select="record" 
        group-by="string-join((field[@name=('EmployeeEmployeeID','ReviewRequest')]),
        '|')">
        <ReviewRequest>
          <EEID>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeEmployeeID']"/>
          </EEID>
          <EEFirstName>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeFirstName']"/>
          </EEFirstName>
          <EEInitial>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeInitial']"/>
          </EEInitial>
          <EELastName>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeLastName']"/>
          </EELastName>
          <EETitle>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeTitle']"/>
          </EETitle>
          <ReviewRequest>
            <xsl:value-of select="current-group()[1]/field[@name='ReviewRequest']"/>
          </ReviewRequest>
            <Goals>
                <xsl:for-each select="current-group()/field[@name='Goal']">
                    <Goal>
                        <Goal><xsl:value-of select="."/></Goal>
                        <Score><xsl:value-of select="../field[@name='Score']"/></Score>
                    </Goal>
                </xsl:for-each>
            </Goals>
        </ReviewRequest>
      </xsl:for-each-group>      
    </Reviews>    
  </xsl:template>

</xsl:stylesheet>

产生这个结果:

<?xml version="1.0" encoding="UTF-8"?>
<Reviews>
   <ReviewRequest>
      <EEID>1234</EEID>
      <EEFirstName>John</EEFirstName>
      <EEInitial>A</EEInitial>
      <EELastName>Doe</EELastName>
      <EETitle>Title</EETitle>
      <ReviewRequest>2017 Review</ReviewRequest>
      <Goals>
         <Goal>
            <Goal>Goal Title1A</Goal>
            <Score>3</Score>
         </Goal>
         <Goal>
            <Goal>Goal Title2A</Goal>
            <Score>2</Score>
         </Goal>
      </Goals>
   </ReviewRequest>
   <ReviewRequest>
      <EEID>1234</EEID>
      <EEFirstName>John</EEFirstName>
      <EEInitial>A</EEInitial>
      <EELastName>Doe</EELastName>
      <EETitle>Title</EETitle>
      <ReviewRequest>2018 Review</ReviewRequest>
      <Goals>
         <Goal>
            <Goal>Goal Title1B</Goal>
            <Score>2</Score>
         </Goal>
         <Goal>
            <Goal>Goal Title2B</Goal>
            <Score>3</Score>
         </Goal>
      </Goals>
   </ReviewRequest>
</Reviews>

http://xsltfiddle.liberty-development.net/bFukv8v/2

1 个答案:

答案 0 :(得分:1)

您获得的输出是built-in template rules的结果。这是因为您没有考虑默认命名空间(http://www.taleo.com/ws/integration/toolkit/2005/07)。所以/ExportXML并不匹配任何内容。

除了考虑默认命名空间之外,还要考虑使用复合group-by而不是两个嵌套for-each-group&#39; s。

分组键是&#34; EmployeeEmployeeID&#34;的组合。字段和&#34; ReviewRequest&#34;领域。

假设除了目标之外的所有内容对于每个组都是相同的,您可以执行以下操作:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/ExportXML">
    <Reviews>
      <xsl:for-each-group select="record" 
        group-by="string-join((field[@name=('EmployeeEmployeeID','ReviewRequest')]),
        '|')">
        <ReviewRequest>
          <EEID>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeEmployeeID']"/>
          </EEID>
          <EEFirstName>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeFirstName']"/>
          </EEFirstName>
          <EEInitial>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeInitial']"/>
          </EEInitial>
          <EELastName>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeLastName']"/>
          </EELastName>
          <EETitle>
            <xsl:value-of select="current-group()[1]/field[@name='EmployeeTitle']"/>
          </EETitle>
          <ReviewRequest>
            <xsl:value-of select="current-group()[1]/field[@name='ReviewRequest']"/>
          </ReviewRequest>
          <xsl:for-each select="current-group()/field[@name='Goal']">
            <Goal><xsl:value-of select="."/></Goal>
          </xsl:for-each>
        </ReviewRequest>
      </xsl:for-each-group>      
    </Reviews>
  </xsl:template>

</xsl:stylesheet>

小提琴:http://xsltfiddle.liberty-development.net/948Fn5t

您还可以稍微简化元素创建(这也可以解释您添加的Score要求)...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/ExportXML">
    <Reviews>
      <xsl:for-each-group select="record" 
        group-by="string-join((field[@name=('EmployeeEmployeeID','ReviewRequest')]),
        '|')">
        <ReviewRequest>
          <xsl:apply-templates 
            select="current-group()[1]/field[not(@name=('Goal','Score'))]"/>
          <Goals>
            <xsl:apply-templates select="current-group()/field[@name='Goal']"/>
          </Goals>
        </ReviewRequest>
      </xsl:for-each-group>      
    </Reviews>
  </xsl:template>

  <xsl:template match="field[@name='Goal']">
    <Goal>
      <Goal><xsl:value-of select="."/></Goal>
      <xsl:apply-templates select="../field[@name='Score']"/>
    </Goal>
  </xsl:template>

  <xsl:template match="field">
    <xsl:element name="{replace(@name,'^(Employee)+(.*)','EE$2')}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

更新了小提琴:http://xsltfiddle.liberty-development.net/948Fn5t/2