简体   繁体   English

通过具有路径的属性重写xml

[英]rewrite xml by attributes with path

although I have seen and read many posts about how to convert attributes to elements no example does what I need. 尽管我已经阅读并阅读了许多有关如何将属性转换为元素的文章,但我并不需要任何示例。 I have a flat xml and will convert it to a full tree oriented xml: 我有一个扁平的xml并将其转换为面向全树的xml:

Input: 输入:

<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>

desired output: 所需的输出:

<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>

I prefer a CSharp solution. 我更喜欢CSharp解决方案。

Thanks for your help 谢谢你的帮助

Here's an XSLT 2.0 solution (there are a couple of XSLT 2.0 processors that you can invoke easily from C#). 这是一个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>

Unlike most of my answers, this is complete and tested to give the output you require, at least on the example document you have provided. 与我的大多数答案不同,这是完整的并且经过测试,至少在您提供的示例文档中可以提供所需的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM