0

尽管我已经看过并阅读了许多关于如何将属性转换为元素的帖子,但没有任何示例可以满足我的需求。我有一个平面 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 解决方案。

谢谢你的帮助

4

1 回答 1

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>

与我的大多数答案不同,这是完整的并且经过测试可以提供您需要的输出,至少在您提供的示例文档上。

于 2012-06-25T14:11:45.320 回答