首页 文章

muenchian分组从xsl键创建节点

提问于
浏览
0

使用xsl键解析一些唯一条目,并使用键中的键值创建新节点 .

以下xml:

<Services>
        <Service Name="Publish" TypeName="FzUDP.Publish" ProviderName="FzUDP" Position="69,102.533530201483" InitPriority="1">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Encryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
        <Service Name="Subscribe" TypeName="FzUDP.Subscribe" ProviderName="FzUDP_1" Position="547,107.533530201483" InitPriority="2">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Decryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
<Service Name="Subscribe2" TypeName="FzUDP.Subscribe" ProviderName="FzUDP_1" Position="547,107.533530201483" InitPriority="2">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Decryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
</Services>

需要转变为:

<ServiceProviders>
<ServiceProvider Name="FzUDP" TypeName="FzUDP">
    <Services>
        <Service Name="Publish" TypeName="Publish" InitPriority="1">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Encryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
        <Service Name="Subscribe" TypeName="Subscribe" InitPriority="2">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Decryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
    </Services>
</ServiceProvider>  
<ServiceProvider Name="FzUDP_1" TypeName="FzUDP">
    <Services>
        <Service Name="Subscribe2" TypeName="Subscribe" InitPriority="2">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Decryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
    </Services>
</ServiceProvider>

我到目前为止提出的xsl代码是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>

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

<xsl:key name="uniqueProviders" match="Service[@ProviderName]" use="Service[@Name]" />


<xsl:template match="Services">
<ServiceProviders>
  <xsl:for-each select=?>


  </xsl:for-each>


</ServiceProviders>
</xsl:template>
</xsl:stylesheet>

我试图在Service元素中使用ProviderName并将它们作为键和服务名称作为值 . 但我不知道如何使用它们 . 另请注意:

a. Attribute Position is not required in the transformed XML.
b. The TypeName attribute of the ServiceProvider element is the first '.' split of the TypeName attribute of the Service element.

所以我认为需要在ServiceProviders之后创建Service元素,但可能会复制Parameter元素 . 我从哪里开始?

编辑1:我使用XSLT 2.0获得了以下内容

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:saxon="http://saxon.sf.net/"
                extension-element-prefixes="saxon"
  xmlns:bootFile="http://tempuri.org/BootfileDefinition"
                xmlns:apps="http://tempuri.org/FZDevice">

  <xsl:output method="xml" indent="yes"/>


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



  <xsl:template match ="//apps:Services">
    <xsl:element name="ServiceProviders">
      <xsl:for-each-group select="//apps:Service" group-by="//apps:Service/@ProviderName">
        <xsl:element name="ServiceProvider">
          <xsl:attribute name="Name">
            <xsl:value-of select="current-grouping-key()"/>
          </xsl:attribute>

          <xsl:attribute name="TypeName">
            <xsl:value-of select="tokenize(current-group()[1]/@TypeName, '\.')[1]"/>
          </xsl:attribute>

          <xsl:for-each select="current-group()">
            <xsl:element name="Service">

              <xsl:attribute name="Name">
                <xsl:value-of select="@Name"/>
              </xsl:attribute>

              <xsl:attribute name="TypeName">
                <xsl:value-of select="tokenize(@TypeName, '\.')[2]"/>
              </xsl:attribute>

              <xsl:attribute name="InitPriority">
                <xsl:value-of select="@InitPriority"/>
              </xsl:attribute>

              <xsl:copy-of select="//apps:Parameter"/>

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

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


</xsl:stylesheet>

请注意,元素名称前面有名称空间 . 我会在输出XML中删除它们,如果有人可以帮我在XSLT 1.0中做同样的事情,我会很感激 .

1 回答

  • 1

    考虑对Muenchian Grouping的这种调整,因为您不需要身份转换,而是重写为分组密钥定制的服务模板 . 另外,要按周期分割 @TypeName 内容,请使用 substring-beforesubstring-after 函数 . 而且似乎你希望 <xsl:key>@ProviderName@TypeName (在句号部分之前)的串联 .

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                                  xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
        <xsl:output method="xml" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:key name="uniqueProviders" match="Service" use="concat(@ProviderName, substring-before(@TypeName, '.'))" />
    
        <xsl:template match="/Services">
            <ServiceProviders>
                <xsl:apply-templates select="Service"/>
            </ServiceProviders>
        </xsl:template>  
    
        <xsl:template match="Service[generate-id() = generate-id(key('uniqueProviders', concat(@ProviderName, substring-before(@TypeName, '.')))[1])]">
            <ServiceProvider Name="{@ProviderName}" TypeName="{substring-before(@TypeName, '.')}">
                <xsl:for-each select="key('uniqueProviders', concat(@ProviderName, substring-before(@TypeName, '.')))">
                    <Service Name="{@Name}" TypeName="{substring-after(@TypeName, '.')}" InitPriority="{@InitPriority}">
                        <xsl:copy-of select="*"/>
                    </Service>       
                </xsl:for-each>
            </ServiceProvider>
        </xsl:template>    
    
    </xsl:stylesheet>
    

    Output

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceProviders>
      <ServiceProvider Name="FzUDP" TypeName="FzUDP">
        <Service Name="Publish" TypeName="Publish" InitPriority="1">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Encryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
      </ServiceProvider>
      <ServiceProvider Name="FzUDP_1" TypeName="FzUDP">
        <Service Name="Subscribe" TypeName="Subscribe" InitPriority="2">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Decryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
        <Service Name="Subscribe2" TypeName="Subscribe" InitPriority="2">
          <Parameter Name="MultiCastIp" Value="224.0.0.0" />
          <Parameter Name="MultiCastPort" Value="61499" />
          <Parameter Name="Decryption" Value="0" />
          <Parameter Name="PacketFormat" Value="0" />
        </Service>
      </ServiceProvider>
    </ServiceProviders>
    

相关问题