[英]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.