Question

J'ai deux documents - l'un est un format de fichier XML personnalisé, l'autre est un flux RSS avec de nombreuses extensions personnalisées. Je souhaite remplir les champs du fichier XML avec les valeurs trouvées dans le flux RSS lorsqu'une valeur d'élément correspond.

Il s’agit d’un processus hors ligne qui sera exécuté plusieurs fois manuellement - il n’a pas besoin d’être performant, il doit être tolérant aux pannes, etc. Le travail ou l’intervention manuelle convient.

Mon document maître XML ressemble à ceci:

    <videos>
        <video>
            <title>First Video</title>
            <code>AAA123</code>
            <id>decaf-decaf-decaf-decaf</id>
            <description>lots of text here...</description>
        </video>
        <video>
            <title>Second Video with no code</title>
            <code></code>
            <id>badab-badab-badab-badab</id>
            <description>lots of text here...</description>
        </video>
    </videos>

Le flux RSS est un flux RSS standard avec quelques champs supplémentaires:

  <ns:code>AAA123</ns:code>
  <ns:type>Awesome</ns:type>
  <ns:group>Wonderful</ns:group>

J'aimerais extraire les champs supplémentaires du document RSS dans le document XML lorsque la valeur correspond à la valeur:

    <videos>
        <video>
            <title>First Video</title>
            <code>AAA123</code>
            <id>decaf-decaf-decaf-decaf</id>
            <description>lots of text here...</description>
            <type>Awesome</type>
            <group>Wonderful</group>
        </video>
        <video>
            <title>Second Video with no code</title>
            <code></code>
            <id>badab-badab-badab-badab</id>
            <description>lots of text here...</description>
            <type></type>
            <group></group>
        </video>
    </videos>

Je préférerais utiliser c #, LINQ ou une sorte de fichier Excel-fu. J'imagine que si je devais le faire, je pourrais traiter avec XSLT tant que cela n'implique pas que j'écrive beaucoup de XSLT moi-même.

J'ai regardé cette question, mais cela ne m'a pas semblé très utile pour ce que j'essaie de faire: Fusion de documents XML

Était-ce utile?

La solution

Cela ressemble à un travail pour LINQ to XML!

var vidDoc = XDocument.Parse(vidXml);
var rssDoc = XDocument.Parse(rssXml);
var videos = vidDoc.XPathSelectElements("/videos/video");
var rssItems = rssDoc.XPathSelectElements("/rss/channel/item");
var matches = videos.Join(
    rssItems,
    video => video.Element(XName.Get("code")).Value,
    rssItem => rssItem.Element(XName.Get("code", "http://test.com")).Value,
    (video, item) => new {video, item});

foreach (var match in matches)
{
    var children = match.item.Elements()
        .Where(child => child.Name.NamespaceName == "http://test.com" &&
                        child.Name.LocalName != "code");

    foreach (var child in children)
    {
        //remove the namespace
        child.Name = XName.Get(child.Name.LocalName);
        match.video.Add(child);
    }
}

vidDoc.Save(Console.Out);

La solution ci-dessus suppose que le document RSS ressemble à ceci:

<rss xmlns:ns="http://test.com" version="2.0">
  <channel>
    <item>
      <title>AAA123</title>
      <link>http://test.com/AAA123</link>
      <pubDate>Sun, 26 Jul 2009 23:59:59 -0800</pubDate>
      <ns:code>AAA123</ns:code>
      <ns:type>Awesome</ns:type>
      <ns:group>Wonderful</ns:group>
    </item>
  </channel>
</rss>

Autres conseils

Ajoutez ceci à une transformation d'identité XSLT (vous aurez également besoin d'ajouter la déclaration d'espace de noms pour l'espace de noms http://test.com à l'élément de niveau supérieur de la transformation):

<xsl:variable name="rss" select="document('rss.xml')"/>

<xsl:template match="video">
   <xsl:apply-templates select="@* | node()"/>
   <xsl:apply-templates select="$rss/rss/channel/item[ns:code=current()/code]"/>
</xsl:template>

<!-- this keeps the code element from getting copied -->
<xsl:template match="ns:code"/>

<!-- this will copy all of the content of the ns:* elements, not just their text -->
<xsl:template match="ns:*">
   <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@* | node()"/>
   </xsl:element>
</xsl:template>

Si vous avez déjà lu le RSS dans un XmlDocument de votre programme, vous pouvez le transférer dans le XSLT en tant que paramètre au lieu d'utiliser la fonction document () . pour le lire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top