当前位置: 首页 > 知识库问答 >
问题:

如何使用xslt转换将多个子元素添加到新的父元素中

严曜文
2023-03-14

我将ExtendedXmlSerializer与C结合使用,一个已知的限制是添加对象的序列化列表。当这样做时,它会产生一个单独的元素(列表本身),其中包含列表中的项目。由于我正在反序列化来自一个单独应用程序的外部xml,我无法控制xml的布局,因此需要在用C#反序列化xml之前对其进行转换。

我在stackoverflow的其他地方找到的转换在将一种类型的元素添加到一个新的(不存在的)元素中时效果很好,但在尝试使用多种不同类型时失败。

我试图尽可能简化源xml:

<?xml version="1.0" encoding="utf-8"?>
<Document>
  <Engineering version="V16" /> <!-- some other elements besides Engineering as well -->
  <SW.Blocks.FB ID="0">
    <AttributeList>
      <AutoNumber>true</AutoNumber>
      <!--more elements including where "Member" is eventually -->
    </AttributeList>
    <ObjectList>
      <MultilingualText ID="1" CompositionName="Comment"/>
      <SW.Blocks.CompileUnit ID="D" CompositionName="CompileUnits"/>
      <SW.Blocks.CompileUnit ID="26" CompositionName="CompileUnits"/>
      <SW.Blocks.CompileUnit ID="3F" CompositionName="CompileUnits"/>
      <SW.Blocks.CompileUnit ID="58" CompositionName="CompileUnits"/>
      <MultilingualText ID="71" CompositionName="Title"/>
    </ObjectList>
  </SW.Blocks.FB>
</Document>

其中首选输出如下:

<Document>
  <Engineering version="V16" />
  <!-- some other elements besides Engineering as well -->
  <SW.Blocks.FB ID="0">
    <AttributeList>
      <AutoNumber>true</AutoNumber>
      <!--more elements including where "Member" is eventually -->
    </AttributeList>
    <ObjectList>
      <CompileUnitToRemove>
        <SW.Blocks.CompileUnit ID="D" CompositionName="CompileUnits" />
        <SW.Blocks.CompileUnit ID="26" CompositionName="CompileUnits" />
        <SW.Blocks.CompileUnit ID="3F" CompositionName="CompileUnits" />
        <SW.Blocks.CompileUnit ID="58" CompositionName="CompileUnits" />
      </CompileUnitToRemove>
      <MultilingualTextToRemove>
        <MultilingualText ID="1" CompositionName="Comment" />
        <MultilingualText ID="71" CompositionName="Title" />
      </MultilingualTextToRemove>
    </ObjectList>
  </SW.Blocks.FB>
</Document>

就像我上面说的,CompileUnitToRemove和MultilLanguage alTextToRemove元素是为了使ExtendedXmlSerializer与列表一起工作。

我目前的xslt如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>

<!-- copy all elements over, except what falls into other template -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- if local name (namespace independent) is 'Member': -->
<xsl:template match="*[local-name(.)='Member']">
<!-- store namespace of Member in variable-->
 <xsl:variable name="ns" select="namespace-uri()" />
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[not(self::*[local-name(.)='SubElement'])]"/>
        <!-- copy everything (except Subelements) over and create a new element "SubElements" with same nameSpace as parent (Member) -->
        <xsl:element name="SubElements" namespace="{$ns}">
        <!-- copy all Subelements over into new element -->
            <xsl:apply-templates select="*[local-name(.)='SubElement']"/>        
        </xsl:element>
    </xsl:copy>
</xsl:template>

<!-- works the same as above, but trying with 2 items within ObjectList: -->
<xsl:template match="*[local-name(.)='ObjectList']">
 <xsl:variable name="ns" select="namespace-uri()" />
 <xsl:copy>
    <xsl:apply-templates select="@*|node()[not(self::*[local-name(.)='SW.Blocks.CompileUnit'])]"/>
        <xsl:element name="CompileUnitToRemove" namespace="{$ns}">
            <xsl:apply-templates select="*[local-name(.)='SW.Blocks.CompileUnit']"/>        
        </xsl:element>
        
        <xsl:apply-templates select="@*|node()[not(self::*[local-name(.)='MultilingualText'])]"/>
        <xsl:element name="MultilingualTextToRemove" namespace="{$ns}">
            <xsl:apply-templates select="*[local-name(.)='MultilingualText']"/>        
        </xsl:element>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

但是,这会创建以下xml:

<Document>
  <Engineering version="V16" />
  <!-- some other elements besides Engineering as well -->
  <SW.Blocks.FB ID="0">
    <AttributeList>
      <AutoNumber>true</AutoNumber>
      <!--more elements including where "Member" is eventually -->
    </AttributeList>
    <ObjectList>
      <MultilingualText ID="1" CompositionName="Comment" />
      <MultilingualText ID="71" CompositionName="Title" />
      <CompileUnitToRemove>
        <SW.Blocks.CompileUnit ID="D" CompositionName="CompileUnits" />
        <SW.Blocks.CompileUnit ID="26" CompositionName="CompileUnits" />
        <SW.Blocks.CompileUnit ID="3F" CompositionName="CompileUnits" />
        <SW.Blocks.CompileUnit ID="58" CompositionName="CompileUnits" />
      </CompileUnitToRemove>
      <SW.Blocks.CompileUnit ID="D" CompositionName="CompileUnits" />
      <SW.Blocks.CompileUnit ID="26" CompositionName="CompileUnits" />
      <SW.Blocks.CompileUnit ID="3F" CompositionName="CompileUnits" />
      <SW.Blocks.CompileUnit ID="58" CompositionName="CompileUnits" />
      <MultilingualTextToRemove>
        <MultilingualText ID="1" CompositionName="Comment" />
        <MultilingualText ID="71" CompositionName="Title" />
      </MultilingualTextToRemove>
    </ObjectList>
  </SW.Blocks.FB>
</Document>

如您所见,其中的元素是重复的。

我还尝试将“xsl:apply-templates”部分放在它自己的“xsl:copy”部分中,也放在它自己的“xsl:copy”部分中

如果有人能帮我弄清楚正确的xslt布局需要什么,那将不胜感激。我也可以为ExtendedXmlSerializer listes-问题提供另一种解决方法,但我确实需要ExtendedXmlSerializer出于其他原因,并且使用xslt是开发人员推荐的解决方案。

共有1个答案

张宝
2023-03-14

以下模板是否满足您的要求?

<xsl:template match="ObjectList">
  <ObjectList>
    <CompileUnitToRemove>
      <xsl:apply-templates select="SW.Blocks.CompileUnit"/>
    </CompileUnitToRemove>
    <MultilingualTextToRemove>
      <xsl:apply-templates select="MultilingualText"/>
    </MultilingualTextToRemove>
  </ObjectList>
</xsl:template>
 类似资料:
  • 我正在将XML导入Access数据库。在转换过程中,数据之间的所有关系都会丢失。使用XSLT,我通过子节点将ID永久化。使用它,其中Id是添加到子节点的父元素: 我使用这种方法遇到的问题是父节点之外还有其他元素也具有元素或其变体,例如或类似的东西。当我尝试在上面的代码之外使用它时,的一些实例在以前的节点中丢失了。 很抱歉,我不知道在这里使用合适的语言,因为我对XSLT/XML不太熟悉。。。但我试图

  • 我通过以下方式通过文本找到了一个孩子。 问题是我需要单击父元素。页面上的元素是动态显示的,之前我只知道文本。是否可以对此进行编程? 我的html:

  • 问题内容: 能够将常规元素临时转换为会非常有用。例如,假设我有一个想要翻转的样式。我想动态创建画布,将其“渲染” 到画布中,隐藏原始元素并为画布设置动画。 能做到吗 问题答案: 抱歉,浏览器无法将HTML渲染到画布中。 如果可能的话,这将带来潜在的安全风险,因为HTML可以包含来自第三方站点的内容(尤其是图像和iframe)。如果可以将HTML内容转换为图像,然后读取图像数据,则有可能从其他站点提

  • 我正在使用TestCafe选择器来选择元素。这是一个复杂的Custin Child嵌套场景。 下面是HTML以了解我上面提到的内容: 在图片中,我提到了和,它们是父元素(具有相同的DOM),有一个grand grand child,而另一棵树中相同父元素的grand grand child是。我需要,但需要链接,因为所有父节点都有相同的DOM。

  • 急求!子元素设置了float:left,为什么是浮动到父元素的父元素(part1)上,而不是浮动到父元素(box1)上?想让这个子元素和学院新闻同行应该怎么办? 这是那个子元素 这是那个子元素 这是整体:

  • 问题内容: 假设我有以下代码: 现在,我需要在上面,但是在jsFiddle中,您可以看到child元素呈现在before之前。 如果您删除 类 或 ,则一切正常。这是我需要的正确行为: http //jsfiddle.net/ZjXMR/1/ 如何在不删除页面的情况下执行此操作? 问题答案: 这是不可能的,因为子级的设置与父级的堆叠索引相同。 您已经通过从父级移除z-index来解决该问题,将其保