LINQ или XSLT, чтобы превратить один элемент в другой в Visual Basic 9 - PullRequest
2 голосов
/ 27 ноября 2008

Короткая версия:

Может ли кто-нибудь предложить или предоставить образец в LINQ to XML для VB или в XSLT о том, как преобразовать один элемент XML в другой (без жесткого кодирования поэлементной копии всех неизмененных элементов)?

Справочная информация:

У меня есть XML-файл, который, как мне кажется, сформирован правильно, который содержит корневую запись <collection> и несколько элементов <dvd>. На DVD есть жанры и теги, как показано ниже. (Я вырезал много других элементов для простоты).

То, что я хочу сделать, это превратить любые элементы <Tag>, которые могут присутствовать, в дополнительный <Genre>. Например, в приведенной ниже записи мне нужно добавить <Genre> Kids </Genre>. (Я понимаю, что на самом деле это атрибут NAME элемента TAG, который я хочу превратить в элемент GENRE, но если бы я мог даже выяснить, как создать новый GENRE под названием «Tag», я был бы намного дальше и, вероятно, может озадачить остальных.)

Я никогда ничего не делал с 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>

Ответы [ 4 ]

2 голосов
/ 27 ноября 2008

Используя один из самых фундаментальных и мощных шаблонов проектирования XSLT: переопределяя шаблон идентификации , вы запишете это очень простое преобразование, чтобы заменить каждый элемент «Жанры» на «Темы». "элемент:

<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>

Применительно к предоставленному исходному документу 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>

Требуемый результат получен:

<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>

Первый шаблон в таблице стилей - это правило идентификации. Он копирует любой сопоставленный узел без изменений и рекурсивно применяет шаблоны к его атрибутам или дочерним элементам. Если другой шаблон отсутствует, этот шаблон создает идентичную копию исходного XML-документа, отсюда и его имя.

Когда существует более конкретный шаблон (определяющий более конкретные детали для сопоставляемого узла, такие как имя и / или другие условия), говорят, что он «переопределяет» более общие шаблоны. Это означает, что для обработки узла выбран более конкретный шаблон.

Используя этот чрезвычайно мощный шаблон проектирования, тривиально реализовать такую ​​обработку как:

  1. Удалить все узлы, которые удовлетворяют некоторому условию.
  2. Переименуйте все узлы, которые удовлетворяют некоторому условию.
  3. Изменить содержимое всех узлов, которые удовлетворяют некоторому условию

при копировании всех остальных узлов без изменений.

В нашем случае второй шаблон более конкретен, и он выбирается для обработки каждого элемента с именем «Жанры». Все, что он делает, это создает элемент с именем «Темы» и внутри него применяет шаблоны ко всем текущим атрибутам узла и дочерним элементам.

Наконец, , следующее преобразование добавит новый элемент "Genre" к потомкам "Genres" для каждого элемента "Tag" :

<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>

Результат снова соответствует требованию:

<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>

Можно найти больше фрагментов кода, использующих шаблон «правила идентификации» здесь .

1 голос
/ 27 ноября 2008

Вы можете сопоставить любой узел с node(), например:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- Uncomment to remove Tags elements -->
<!-- <xsl:template match="Tags" /> -->

<xsl:template match="Genres">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
        <xsl:for-each select="../Tags/Tag">
            <xsl:element name="Genre">
                <xsl:value-of select="@Name" />
            </xsl:element>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<!-- Default rule: Copy node and descend -->
<xsl:template match="@*|node()">
        <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
</xsl:template>

</xsl:stylesheet>
0 голосов
/ 05 сентября 2009

У меня была такая же потребность в VB9 и я хотел использовать Linq вместо XSL. Я нашел это: http://msdn.microsoft.com/en-us/library/bb669154.aspx, и это сработало очень хорошо.

0 голосов
/ 27 ноября 2008

Вы ищете что-то вроде этого:

 <xsl:template match="Tag">
    <xsl:element name="Genre">
      <xsl:value-of select="@Name"/>           
    </xsl:element>    
  </xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...