質問

2つのドキュメントがあります。1つはカスタムXMLファイル形式で、もう1つは多数のカスタム拡張機能を備えたRSSフィードです。 1つの要素の値が一致したときに、RSSフィードで見つかった値をXMLファイルのフィールドに入力します。

これは、手動で数回実行されるオフラインプロセス用です-うまく機能する必要はなく、フォールトトレラントである必要もありません。手作業や介入は問題ありません。

マスターXMLドキュメントは次のようになります。

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

RSSフィードは、追加のフィールドを含む標準RSSです:

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

の値が次の値と一致したときに、RSSドキュメントからXMLドキュメントに追加のフィールドを引き出したい:

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

C#、LINQ、または何らかのExcel-fuを使用したいです。 XSLTを自分で書く必要がなければ、XSLTに対処できなければならないと思います。

この質問を見てみましたが、私がやろうとしていることにはそれほど役立つとは思えませんでした。 XMLドキュメントのマージ

役に立ちましたか?

解決

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

上記のソリューションでは、RSSドキュメントが次のようになっていることを前提としています。

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

他のヒント

これをXSLT ID変換に追加します( http://test.com 名前空間の名前空間宣言を変換のトップレベル要素に追加する必要もあります):

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

RSSをプログラムの XmlDocument に既に読み込んでいる場合、 document()関数を使用する代わりに、パラメータとしてXSLTにRSSを渡すことができます。読んでください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top