Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.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
Xslt转换/如何对实体进行分组_Xslt - Fatal编程技术网

Xslt转换/如何对实体进行分组

Xslt转换/如何对实体进行分组,xslt,Xslt,我想使用XSLT修改: <Office Code="1" OtherAttribute="5"> <Customer CustomerId="0010" CodeModifier="A"/> <Customer CustomerId="0011" CodeModifier="B"/> <Customer CustomerId="0012" CodeModifier="B"/> </Office> <Office

我想使用XSLT修改:

<Office Code="1" OtherAttribute="5">
   <Customer CustomerId="0010" CodeModifier="A"/>
   <Customer CustomerId="0011" CodeModifier="B"/>
   <Customer CustomerId="0012" CodeModifier="B"/>
</Office>
<Office Code="2" OtherAttribute="6">
   <Customer CustomerId="2010" CodeModifier="A"/>
   <Customer CustomerId="0011" CodeModifier="C"/>
</Office>

进入:

<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011"/>
   <Customer CustomerId="0012"/>
</Office>
<Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011"/>
</Office>

我的目标:

  • 将具有相同CodeModifier的每个客户实体分组为Office实体。如果有多个CodeModifier,我将添加Office实体。将修改Office中的Code属性(将客户端的CodeModifier连接到Office中)
  • (兼性但我认为很琐碎)抑制CodeModifier属性并保留所有其他属性

有人知道怎么做吗?

此样式表应用于您的输入示例:

<!-- a key to group Customers by their office code + modifier -->
<xsl:key name="kCustomerGroup" match="Customer" 
  use="concat(../@Code, @CodeModifier)" 
/>

<!-- identity template: copies everything that is not handled otherwise -->
<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

<!-- apply templates directly to customers. modify as necessary -->
<xsl:template match="/">
  <xsl:apply-templates select="//Customer" mode="CustomerGroup" />
</xsl:template>

<xsl:template match="Customer" mode="CustomerGroup">
  <xsl:variable name="officeCode" select="concat(../@Code, @CodeModifier)" />
  <!-- if this Customer is first of his respective group... -->
  <xsl:if test="
    generate-id() 
    =
    generate-id(key('kCustomerGroup', $officeCode)[1])
  ">
    <!-- use for-each to switch the context node to the parent -->
    <xsl:for-each select="..">
      <xsl:copy>
        <xsl:apply-templates select="@*" />
        <!-- overwrite the @Code attribute -->
        <xsl:attribute name="Code">
          <xsl:value-of select="$officeCode" />
        </xsl:attribute>
        <!-- now handle the Customer group members -->
        <xsl:apply-templates select="key('kCustomerGroup', $officeCode)" />
      </xsl:copy>
    </xsl:for-each>
  </xsl:if>
</xsl:template>

<!-- remove unwanted attribute with empty template -->    
<xsl:template match="Customer/@CodeModifier" />


此样式表应用于您的输入示例:

<!-- a key to group Customers by their office code + modifier -->
<xsl:key name="kCustomerGroup" match="Customer" 
  use="concat(../@Code, @CodeModifier)" 
/>

<!-- identity template: copies everything that is not handled otherwise -->
<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

<!-- apply templates directly to customers. modify as necessary -->
<xsl:template match="/">
  <xsl:apply-templates select="//Customer" mode="CustomerGroup" />
</xsl:template>

<xsl:template match="Customer" mode="CustomerGroup">
  <xsl:variable name="officeCode" select="concat(../@Code, @CodeModifier)" />
  <!-- if this Customer is first of his respective group... -->
  <xsl:if test="
    generate-id() 
    =
    generate-id(key('kCustomerGroup', $officeCode)[1])
  ">
    <!-- use for-each to switch the context node to the parent -->
    <xsl:for-each select="..">
      <xsl:copy>
        <xsl:apply-templates select="@*" />
        <!-- overwrite the @Code attribute -->
        <xsl:attribute name="Code">
          <xsl:value-of select="$officeCode" />
        </xsl:attribute>
        <!-- now handle the Customer group members -->
        <xsl:apply-templates select="key('kCustomerGroup', $officeCode)" />
      </xsl:copy>
    </xsl:for-each>
  </xsl:if>
</xsl:template>

<!-- remove unwanted attribute with empty template -->    
<xsl:template match="Customer/@CodeModifier" />


这里有另一种方法,只使用匹配的模板


MSXSL 4.0下测试为XSLT 1.0

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

    <xsl:key name="kCustomerGroup" match="Customer" 
        use="concat(../@Code, @CodeModifier)" 
        />

    <xsl:template match="Office">
        <xsl:apply-templates select="Customer[generate-id() 
            =
            generate-id(key('kCustomerGroup', 
            concat(../@Code, @CodeModifier))[1])]"
            />
    </xsl:template>

    <xsl:template match="Customer">
        <Office 
            Code="{concat(../@Code,@CodeModifier)}" 
            OtherAttribute="{../@OtherAttribute}">

            <xsl:apply-templates select="key('kCustomerGroup', 
                concat(../@Code,@CodeModifier))" mode="copy"/>

        </Office>
    </xsl:template>

    <xsl:template match="Customer" mode="copy">
        <xsl:copy>
            <xsl:copy-of select="@CustomerId"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

输出至:

<?xml version="1.0" encoding="UTF-8"?>
<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011"/>
   <Customer CustomerId="0012"/>
</Office>
<Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011"/>
</Office>

这里有另一种方法,只使用匹配的模板


MSXSL 4.0下测试为XSLT 1.0

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

    <xsl:key name="kCustomerGroup" match="Customer" 
        use="concat(../@Code, @CodeModifier)" 
        />

    <xsl:template match="Office">
        <xsl:apply-templates select="Customer[generate-id() 
            =
            generate-id(key('kCustomerGroup', 
            concat(../@Code, @CodeModifier))[1])]"
            />
    </xsl:template>

    <xsl:template match="Customer">
        <Office 
            Code="{concat(../@Code,@CodeModifier)}" 
            OtherAttribute="{../@OtherAttribute}">

            <xsl:apply-templates select="key('kCustomerGroup', 
                concat(../@Code,@CodeModifier))" mode="copy"/>

        </Office>
    </xsl:template>

    <xsl:template match="Customer" mode="copy">
        <xsl:copy>
            <xsl:copy-of select="@CustomerId"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

输出至:

<?xml version="1.0" encoding="UTF-8"?>
<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011"/>
   <Customer CustomerId="0012"/>
</Office>
<Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011"/>
</Office>

完整而简短的XSLT 2.0解决方案

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

 <xsl:template match="/*/*">
  <xsl:for-each-group select="Customer" group-by="@CodeModifier">
   <Office>
     <xsl:copy-of select="../@*"/>
     <xsl:attribute name="Code" select=
         "concat(../@Code, current-grouping-key())"/>
     <xsl:copy-of select="current-group()"/>
   </Office>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011" CodeModifier="B"/>
   <Customer CustomerId="0012" CodeModifier="B"/>
</Office>
    <Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011" CodeModifier="C"/>
</Office>

应用于以下XML文档时(基于提供的XML片段,并将其包装到单个顶部元素中,使其成为格式良好的XML文档):


生成所需的正确结果

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

 <xsl:template match="/*/*">
  <xsl:for-each-group select="Customer" group-by="@CodeModifier">
   <Office>
     <xsl:copy-of select="../@*"/>
     <xsl:attribute name="Code" select=
         "concat(../@Code, current-grouping-key())"/>
     <xsl:copy-of select="current-group()"/>
   </Office>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011" CodeModifier="B"/>
   <Customer CustomerId="0012" CodeModifier="B"/>
</Office>
    <Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011" CodeModifier="C"/>
</Office>

完整而简短的XSLT 2.0解决方案

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

 <xsl:template match="/*/*">
  <xsl:for-each-group select="Customer" group-by="@CodeModifier">
   <Office>
     <xsl:copy-of select="../@*"/>
     <xsl:attribute name="Code" select=
         "concat(../@Code, current-grouping-key())"/>
     <xsl:copy-of select="current-group()"/>
   </Office>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011" CodeModifier="B"/>
   <Customer CustomerId="0012" CodeModifier="B"/>
</Office>
    <Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011" CodeModifier="C"/>
</Office>

应用于以下XML文档时(基于提供的XML片段,并将其包装到单个顶部元素中,使其成为格式良好的XML文档):


生成所需的正确结果

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

 <xsl:template match="/*/*">
  <xsl:for-each-group select="Customer" group-by="@CodeModifier">
   <Office>
     <xsl:copy-of select="../@*"/>
     <xsl:attribute name="Code" select=
         "concat(../@Code, current-grouping-key())"/>
     <xsl:copy-of select="current-group()"/>
   </Office>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
   <Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
   <Customer CustomerId="0011" CodeModifier="B"/>
   <Customer CustomerId="0012" CodeModifier="B"/>
</Office>
    <Office Code="2A" OtherAttribute="6">
   <Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
   <Customer CustomerId="0011" CodeModifier="C"/>
</Office>


您使用的条件与我一样。只有您的条件在谓词中,而我的条件在
;-)如果你仔细观察的话,我不会使用循环来做任何工作。你使用的条件和我一样。只有您的条件在谓词中,而我的条件在
;-)如果你仔细看的话,我不会用循环做任何工作。好问题,+1。请参阅我的答案,了解完整、非常简短且简单的XSLT 2.0解决方案。:)好问题,+1。请参阅我的答案,了解完整、非常简短且简单的XSLT 2.0解决方案。:)