查找和替换节点的内容

时间:2016-02-14 17:09:14

标签: xml c#-4.0 xpath

我有2个XML文档,如下所示:

  1. DOC1

    <?xml version="1.0" encoding="UTF-8"?>
    <import>
      <collection>
        <name>II_14714_1889</name>
        <metadata>512143197.xml</metadata>
      </collection>
      <collection>
        <name>II_14714_1884</name>
        <metadata>512142173.xml</metadata>
      </collection>
      <collection>
        <name>II_14714_1886</name>
        <metadata>512142685.xml</metadata>
      </collection>
    </import>
    
  2. DOC2

    <?xml version="1.0" encoding="UTF-8"?>
    <collection>
      <record>
        <datafield tag="000">
          <subfield code="x">512143197</subfield>
          <subfield code="r">...</subfield>
        </datafield>
        <datafield tag="200">
          <subfield code="e">1989</subfield>
        </datafield>
      </record>
      <record>
        <datafield tag="000">
          <subfield code="x">512143180</subfield>
          <subfield code="r">...</subfield>
        </datafield>
        <datafield tag="200">
          <subfield code="e">1970</subfield>
        </datafield>
      </record>
      <record>
        <datafield tag="000">
          <subfield code="x">512143198</subfield>
          <subfield code="r">...</subfield>
        </datafield>
        <datafield tag="200">
          <subfield code="e">1990</subfield>
        </datafield>
      </record>
    </collection>
    
  3. 我要做的是从doc1中的元数据节点获取文本,在doc2中的子字段代码中搜索它=&#34; x&#34;节点,如果它在那里得到子字段代码=&#34; e&#34;同一记录节点的文本,并用它替换相应的doc1 //集合/名称节点文本。

    目前我正在使用以下代码

    foreach (XmlNode xmlMetadata in doc1.DocumentElement.SelectNodes("//collection/metadata"))
            {
                    string id = xmlMetadata.InnerText.ToString();
                    string resultString = Regex.Match(id, @"\d\d\d\d+").Value;
                    MessageBox.Show(resultString);
                    foreach (XmlNode xmlSubfield in doc2.SelectNodes("//record/datafield[@tag='000']/subfield[@code='x']"))
                    {
                        string subfield = xmlSubfield.InnerText.ToString();
                        if (subfield == resultString)
                        {
                            MessageBox.Show(xmlSubfield.SelectSingleNode("../datafield[@tag='200']/subfield[@code='e']").InnerText.ToString());
                            string year = xmlSubfield.SelectSingleNode("../datafield[@tag='200']/subfield[@code='e']").InnerText.ToString();
                            year = Regex.Match(godina, @"\d\d\d\d").Value;
                            doc2.SelectSingleNode("../datafield[@tag='200']/subfield[@code='e']").InnerText = godina;
                        }
    
                    }
    
    
            }
    

    但它显示&#34;对象引用未设置为对象的实例&#34;第二个MessageBox出错。

1 个答案:

答案 0 :(得分:1)

您正在选择第一个XPath表达式中的所有subfield个节点

//record/datafield[@tag='000']/subfield[@code='x']

因此,您必须在开头添加另一个../MessageBox.Show的XPath表达式,以达到记录节点级别。

MessageBox.Show(xmlSubfield.SelectSingleNode("../../datafield[@tag='200']/subfield[@code='e']").InnerText.ToString());
                                              ^^^ here

编辑:实现这一目标的更简单方法是

foreach (XmlNode xmlSubfield in doc2.SelectNodes("//record[datafield[@tag='000']/subfield[@code='x'] = '"+resultString+"']/datafield[@tag='200']/subfield[@code='e']"))
{ 
  MessageBox.Show(xmlSubfield.InnerText.ToString());
  ...
}