xml - 在 Visual Basic 9 中将一个元素转换为另一个元素的 LINQ 或 XSLT

标签 xml vb.net linq xslt transform

简短版本:

任何人都可以在 LINQ to XML for VB 中建议或提供一个示例,或者在 XSLT 中提供如何将一个 XML 元素更改为另一个 XML 元素的示例(无需对所有未更改元素的逐个元素副本进行硬编码)吗?

背景:

我有一个 XML 文件,我认为该文件格式正确,其中包含根条目 <collection > 和多个<dvd > 元素。 DVD 中包含流派和标签,如下所示。 (为了简单起见,我删除了很多其他元素)。

我想做的是转任何 <Tag > 可能出现在附加 <Genre 中的元素>。例如,在下面的条目中,我需要添加 <Genre > child </Genre >。 (我意识到,我实际上希望将 TAG 元素的 NAME 属性转换为 GENRE 元素,但如果我能弄清楚如何创建一个名为“Tag”的新 GENRE,我会更进一步并可能解决其余的问题。)

我从来没有对 XML 做过太多事情。我的理解是,我可以使用 XSLT 转换文件和 XSLCompiledTransform,或者我可以使用 LINQ to XML(我有 Visual Basic 9,并且更愿意在 VB 内完成这一切)。 [我确信还有许多其他方法。]

问题是,我找不到任何 XSLT 或 LINQ 语法示例来告诉我如何将一个元素转换为另一个元素。我可以编写足够的 LINQ 来逐一复制所有元素,但必须有一种比硬编码所有不更改元素的副本更简单的方法! (必须有!)

因此,如果知道的人可以给我指出一个示例,或者帮我提供一些 LINQ 或 XSLT 中的入门代码,我将永远感激不已(好吧,也许不是永远,但至少在很长一段时间内) !)。

谢谢。

示例 XML:

<Collection>
  <DVD>
    <ID>0000502461</ID>
    <Title>Cirque du Soleil: Alegría</Title>
    <Released>2002-05-31</Released>
    <RunningTime>90</RunningTime>
    <Genres>
      <Genre>Family</Genre>
      <Genre>Music</Genre>
    </Genres>
    <Overview>What if anything were possible? What if ...
    </Overview>
    <Notes/>
    <Tags>
      <Tag Name="Kids" FullName="Kids"/>
    </Tags>
  </DVD>
</Collection>

最佳答案

使用最基本、最强大的 XSLT 设计模式之一:覆盖 identity template ,我们将编写这个非常简单的转换,用“Topics”元素替换每个“Genres”元素:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output omit-xml-declaration="yes"/>

    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="Genres">
      <Topics>
         <xsl:apply-templates select="node()|@*"/>
      </Topics>
    </xsl:template>
</xsl:stylesheet>

When applied against the provided source XML document:

<Collection>
    <DVD>
        <ID>0000502461</ID>
        <Title>Cirque du Soleil: Alegría</Title>
        <Released>2002-05-31</Released>
        <RunningTime>90</RunningTime>
        <Genres>
            <Genre>Family</Genre>
            <Genre>Music</Genre>
        </Genres>
        <Overview>What if anything were possible? What if ...    </Overview>
        <Notes/>
        <Tags>
            <Tag Name="Kids" FullName="Kids"/>
        </Tags>
    </DVD>
</Collection>

The wanted result is produced:

<Collection>
    <DVD>
        <ID>0000502461</ID>
        <Title>Cirque du Soleil: Alegría</Title>
        <Released>2002-05-31</Released>
        <RunningTime>90</RunningTime>
        <Topics>
            <Genre>Family</Genre>
            <Genre>Music</Genre>
        </Topics>
        <Overview>What if anything were possible? What if ...    </Overview>
        <Notes/>
        <Tags>
            <Tag Name="Kids" FullName="Kids"/>
        </Tags>
    </DVD>
</Collection>

The first template in the stylesheet is the identity rule. It copies any matched node unchanged and recursively applies templates to its attributes or children. If no other template is present, this template creates identical copy of the source xml document, hence its name.

When there is a more specific template (specifying more specific details for the matched node, such as name and/or other conditions), it is said to "override" the more generic templates. This means that the more specific template is chosen for processing the node.

Using this extremely powerful design pattern it is trivial to implementin just a few lines such processing as:

  1. Delete all nodes that satisfy some condition.
  2. Rename all nodes that satisfy some condition.
  3. Modify the contents of all nodes that satisfy some condition

while copying all other nodes intact.

In our case, the second template is more specific and it gets selected for processing of every element named "Genres". All it does is create an element named "Topics" and inside it apply templates to all of the current node attributes and children.

Finally, the following transformation will add a new "Genre" element to the children of "Genres", for each "Tag" element:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output omit-xml-declaration="yes"/>

    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="Genres">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
         <xsl:apply-templates select="../Tags/Tag" mode="Gen"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="Tag" mode="Gen">
      <Genre>
        <xsl:value-of select="@Name"/>
      </Genre>
    </xsl:template>
</xsl:stylesheet>

The result is again as required:

<Collection>
    <DVD>
        <ID>0000502461</ID>
        <Title>Cirque du Soleil: Alegría</Title>
        <Released>2002-05-31</Released>
        <RunningTime>90</RunningTime>
        <Genres>
            <Genre>Family</Genre>
            <Genre>Music</Genre>
        <Genre>Kids</Genre>
        </Genres>
        <Overview>What if anything were possible? What if ...    </Overview>
        <Notes/>
        <Tags>
            <Tag Name="Kids" FullName="Kids"/>
        </Tags>
    </DVD>
</Collection>

可以找到更多使用“身份规则”模式的代码片段 here .

关于xml - 在 Visual Basic 9 中将一个元素转换为另一个元素的 LINQ 或 XSLT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/322496/

相关文章:

javascript - 读取其中包含 ]] 的 XML CDATA 部分

c# - XSLt.transform 给我 ""

mysql - 在测试数据库和生产数据库之间切换?

c# - 如何删除除某些文件夹之外的所有文件夹

java - URL 不存在时出现 SAXParseException

iphone - 如何使用 GDataXML 解析器解析嵌套的 xml?

php - 将 html 页面转换为 pdf

c# - 记录所有在 Windows 中关闭的 Windows

c# - Extending LINQ to Nhibernate provider,结合Dynamic LINQ问题

c# - 在不遇到集合修改异常的情况下从列表中删除项目的最有效方法?