【问题标题】:How do I convert these embedded elements into attributes of the parent element?如何将这些嵌入元素转换为父元素的属性?
【发布时间】:2012-04-19 15:27:42
【问题描述】:

我有一个大型 XSD,其元素如下所示:

<xs:element name="ProgramName" type="xs:string" minOccurs="0">
  <xs:annotation>
    <xs:documentation>PN</xs:documentation> 
  </xs:annotation>
</xs:element>
<xs:element name="TestItem" type="xs:string" minOccurs="0">
  <xs:annotation>
    <xs:documentation>TA</xs:documentation> 
  </xs:annotation>
</xs:element>

我想将&lt;documentation&gt; 元素折叠成祖父元素的一个属性,如下所示:

<xs:element name="ProgramName" type="xs:string" minOccurs="0" code="PN">
</xs:element>
<xs:element name="TestItem" type="xs:string" minOccurs="0" code="TA">
</xs:element>

如何用 XSLT 做到这一点?或者,有没有比 XSLT 更好(阅读:更简单)的方法?

生成的 XSD 将与 XSD.EXE 一起使用以创建 C# 类,用于序列化和反序列化目的。原来的 XSD 不能这样使用,因为XSD.EXE 丢弃了所有的注解元素,所以这些注解中包含的信息丢失了。

【问题讨论】:

    标签: c# xslt serialization xsd


    【解决方案1】:

    这只是另一个答案:)

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes"/>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    
      <xsl:template match="node()[local-name()='element']">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()[local-name()!='annotation']"/>
          <xsl:for-each select="node()[local-name()='annotation']/node()[local-name()='documentation']">
            <xsl:attribute name="code">
              <xsl:value-of select="."/>
            </xsl:attribute>
          </xsl:for-each>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    使用 XSLT 来重新排列节点而不是手动操作确实是一个很好的想法 :) 我总是使用 XSLT ..
    我们甚至可以使用它从 XSD 生成示例 XML .. 如果 XSD 的大小可以承受:)

    【讨论】:

    • 我建议你尝试你的 XSLT 对抗一个也有一些全局类型的 XSD;一个简单的,例如在 SO 上发布的here。你会发现你的不起作用,至少与@DevNull 相比......我会让你找出原因......然后也许你可以更新你的帖子。
    • @PetruGardea,它适用于 OPs 问题.. 如果元素中定义了复杂类型,那么我的代码不起作用我知道.. 那是因为我忽略了其中的所有 ELEMENT 节点&lt;xs:element/&gt;.. 相反,如果他们在 else where 定义 complextype 并将其用作 Element 的类型,它应该可以工作。
    • @PetruGardea,我将立即更新我的答案..以使其工作,例如您提到的。
    • 投反对票的人是否有足够的礼貌让我知道投反对票的原因??
    【解决方案2】:

    这就是我的做法:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="*[xs:annotation]">
        <xsl:copy>
          <xsl:attribute name="code"><xsl:value-of select="xs:annotation/xs:documentation"/></xsl:attribute>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>    
      </xsl:template>
    
      <xsl:template match="xs:annotation"/>      
    
    </xsl:stylesheet>
    

    【讨论】:

    • 谢谢。现在我只需要弄清楚如何针对原始 XSD 执行它。 :P 正如您可能已经猜到的那样,我对 XSLT 的经验为零,尽管我知道它的目的是什么。我向伟大的 XSLT 大师们鞠躬,他们比我开明得多。
    • @RobertHarvey - 我绝对不是大师,但我很高兴能提供帮助。
    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多