2012-06-25 52 views
0

尽管我已经看过并阅读了很多关于如何将属性转换为元素的帖子,没有任何示例做我需要的东西。 我有一个平整的xml并将其转换为一个完整的树面向XML:重写xml的属性与路径

输入:

<Subsystem Name="Device Monitor"> 
<Group Name="ITCHealth"> 
    <Field Name="System\AttachedDevice\OneWire\Count" Type="Integer">0</Field> 
    <Field Name="System\AttachedDevice\OneWire\Asset" Type="String">Str</Field> 
    <Field Name="System\AttachedDevice\USB\Count" Type="Integer">0</Field> 
    <Field Name="System\AttachedDevice\USB\Name" Type="Integer">0</Field> 
    <Field Name="System\Camera\Enabled" Type="Boolean">true</Field> 
    <Field Name="System\Camera\Present" Type="Boolean">true</Field> 
    <Field Name="Network\BlueTooth\RadioStatus" Type="String">Str</Field> 
</Group> 
</Subsystem> 

所需的输出:

<Subsystem Name="Device Monitor"> 
<Group Name="ITCHealth"> 
    <Group Name="System"> 
     <Group Name="AttachedDevice"> 
      <Group Name="OneWire"> 
       <Field Name="Count" Type="Integer">0</Field> 
       <Field Name="Asset" Type="String">Str</Field> 
      </Group> 
      <Group Name="USB "> 
       <Field Name="Count" Type="Integer">0</Field> 
       <Field Name="Name" Type="Integer">0</Field> 
      </Group> 
     </Group> 
     <Group Name="Camera"> 
      <Field Name="Enabled" Type="Boolean">true</Field> 
      <Field Name="Present" Type="Boolean">true</Field> 
     </Group> 
    </Group> 
    <Group Name="Network"> 
     <Group Name="Bluetooth"> 
      <Field Name="Radiostatus" Type="String">Str</Field> 
     </Group> 
    </Group> 
</Group> 
</Subsystem> 

我喜欢CSHARP解决方案。

感谢您的帮助

回答

0

下面是一个XSLT 2.0解决方案(有一对夫妇XSLT 2.0处理器,可以从C#调用容易)。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> 

    <xsl:template match="*"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Group"> 
     <xsl:copy> 
      <xsl:call-template name="group-fields"> 
       <xsl:with-param name="fields" select="Field"/> 
       <xsl:with-param name="depth" select="1"/> 
      </xsl:call-template> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template name="group-fields"> 
     <xsl:param name="fields" as="element(Field)*"/> 
     <xsl:param name="depth"/> 
     <xsl:for-each-group select="$fields" group-by="tokenize(@Name, '\\')[$depth]"> 
      <xsl:choose> 
       <xsl:when test="count(current-group()) = 1 and count(tokenize(@Name, '\\')) = $depth"> 
        <Field Name="{current-grouping-key()}" Type="{@Type}"> 
         <xsl:value-of select="."/> 
        </Field> 
       </xsl:when> 
       <xsl:otherwise> 
        <Group Name="{current-grouping-key()}"> 
         <xsl:call-template name="group-fields"> 
          <xsl:with-param name="fields" select="current-group()"/> 
          <xsl:with-param name="depth" select="$depth + 1"/> 
         </xsl:call-template> 
        </Group> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each-group> 
    </xsl:template> 

</xsl:stylesheet> 

不像大多数我的答案,这是完整的和测试,给出了至少您所提供的示例文件,你需要的输出。

+0

感谢您的解决方案,虽然我无法在紧凑的框架上使用xslt2。 此外,xsl并不会完全产生所需的输出。 – josef

+0

感谢您的解决方案,虽然我无法在紧凑框架上使用xslt2。 此外,xsl并不会完全产生所需的输出。 有一个没有属性的组标签,而不是组名=“ITCHealth”之一。 – josef