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 ソリューションを次に示します (C# から簡単に呼び出すことができる XSLT 2.0 プロセッサがいくつかあります)。

<?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 に答える