【问题标题】:Is it possible in XSL to flatten XML hierarchy?在 XSL 中是否可以展平 XML 层次结构?
【发布时间】:2011-03-26 18:29:09
【问题描述】:

我的 XML 文件结构如下:

<INSTANCE>
  <Sections>
    <Section>
      <Forms>
        <Form>
          <Control id="GroupHeading1">
            <Property/>
            <Property/>
          </Control>
          <Control id="GroupHeading2">
           <Property/>
            <Control id="TextBox">
              <Property/>
              <Property/>
            </Control>
          </Control>
        </Form>
      </Forms>
    </Section>
  </Sections>
</INSTANCE>

我正在尝试将其反序列化为 C# 对象,但我不需要保留层次结构(这使我难以反序列化)。

是否有 XSL 可以将其转换为取消嵌套控件,并在可能的情况下向任何具有 ParentId="" 的子控件添加属性?

感谢您的指导!

【问题讨论】:

  • @user53885:没有所需的输出,这不是一个完整的问题。
  • @user53885 - 鉴于您对@harpo 的回答的评论 - “我正在考虑不要在任何其他控件下设置控件,例如 TextBox 将具有 ParentId="GroupHeading2" 的属性,并且与 GroupHeadings 处于同一级别。” -- 我添加了一个解决方案,其中所有&lt;Control&gt; 元素出现在同一级别。
  • @Alejandro - 最好是明确的示例输出,但 OP 确实比其他人提供了更多关于所需输出的线索
  • @lwburk:有四个小时的 cmets 描述需求...

标签: c# .net xml xslt xml-deserialization


【解决方案1】:

给定 XML,XmlSerializer 可以生成包含相同实例数据的对象图。
这被称为XML de-serialization

你需要看这里:

【讨论】:

    【解决方案2】:

    此模板应该可以帮助您入门。我在 .NET 2.0 上运行它。

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes" method="xml"/>
    
        <xsl:template match="*">
            <xsl:element name="{name()}">
                <xsl:apply-templates select="@*"/>
                <xsl:apply-templates select="*"/>
            </xsl:element>
        </xsl:template>
    
        <xsl:template match="Form">
            <Form>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates select="//Control"/>
            </Form>
        </xsl:template>
    
        <xsl:template match="Control">
            <Control>
                <xsl:if test="ancestor::Control/@id">
                    <xsl:attribute name="ParentID"><xsl:value-of select="ancestor::Control/@id"/></xsl:attribute>
                </xsl:if>
                <xsl:copy-of select="*|@*"/>
            </Control>
        </xsl:template>
    
    </xsl:stylesheet>
    

    这是输出(为了便于阅读而缩进)。

    <INSTANCE>
        <Sections>
            <Section>
                <Forms>
                    <Form>
                        <Control id="GroupHeading1">
                            <Property />
                            <Property />
                        </Control>
                        <Control id="GroupHeading2">
                            <Property />
                            <Control id="TextBox">
                                <Property />
                                <Property />
                            </Control>
                        </Control>
                        <Control ParentID="GroupHeading2" id="TextBox">
                            <Property />
                            <Property />
                        </Control>
                    </Form>
                </Forms>
            </Section>
        </Sections>
    </INSTANCE>
    

    【讨论】:

    • 它不允许我编辑。但我在考虑不要在任何其他控件下方设置一个控件,例如 TextBox 将具有 ParentId="GroupHeading2" 的属性,并且与 GroupHeadings 处于同一级别。
    • 什么不允许你编辑?如果你的意思是你不能就地重写模板文件,你总是可以在反序列化之前在内存中转换它。
    • 对不起,我的意思是我在这里发布的问题本身。它不会让我按照你的要求更新。
    • 再看输出。这就是你得到的。 Control 模板包含在另一个 Control 元素中,该元素在适当的地方具有 ParentID 元素。但是源头上的所有三个控件都处于同一级别。格式化输出的方式当然有很多,但没有任何规范,我只是做了我认为合理的事情。自己尝试转换并根据自己的喜好进行调整。几乎任何类型的基于 XSLT 的扁平化解决方案都会看起来像这样。
    • 谢谢!!!我从您发送的内容中将 标记从第 11 行中取出,它几乎完全符合我的需要 - 除了没有一个输出包含 ParentId。我会尝试弄清楚如何让 ParentId 部分工作。
    【解决方案3】:

    以下样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>
        <!-- first-level control elements -->
        <xsl:template match="Control">
            <Control>
                <xsl:copy-of select="@*|*[not(self::Control)]" />
            </Control>
            <xsl:apply-templates select="Control" />
        </xsl:template>
        <!-- nested control elements -->
        <xsl:template match="Control/Control">
            <Control ParentId="{../@id}">
                <xsl:copy-of select="@*|*[not(self::Control)]" />
            </Control>
            <xsl:apply-templates select="Control" />
        </xsl:template>
    </xsl:stylesheet>
    

    应用于以下文档(与原始文档相同,为演示目的增加了一层嵌套):

    <INSTANCE>
        <Sections>
            <Section>
                <Forms>
                    <Form>
                        <Control id="GroupHeading1">
                            <Property />
                            <Property />
                        </Control>
                        <Control id="GroupHeading2">
                            <Property />
                            <Control id="TextBox">
                                <Property />
                                <Property />
                                <Control id="Grandchild">
                                    <Property />
                                </Control>
                            </Control>
                        </Control>
                    </Form>
                </Forms>
            </Section>
        </Sections>
    </INSTANCE>
    

    产生一个输出没有嵌套的&lt;Control&gt;元素

    <INSTANCE>
        <Sections>
            <Section>
                <Forms>
                    <Form>
                        <Control id="GroupHeading1">
                            <Property />
                            <Property />
                        </Control>
                        <Control id="GroupHeading2">
                            <Property />
                        </Control>
                        <Control ParentId="GroupHeading2" id="TextBox">
                            <Property />
                            <Property />
                        </Control>
                        <Control ParentId="TextBox" id="Grandchild">
                            <Property />
                        </Control>
                    </Form>
                </Forms>
            </Section>
        </Sections>
    </INSTANCE>
    

    【讨论】:

    • 酷,我不知道 xsl:copy 模板。
    猜你喜欢
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    相关资源
    最近更新 更多