C#在测试缺少元素的节点时获取XML中Previous节点的子节点的特定属性

时间:2016-04-27 18:36:19

标签: c# xml lambda linq-to-xml

我有一个xliff我正在尝试获取上一个idx的{​​{1}}元素的source属性的值只要它没有trans-unit孩子。

非常具体地说,我不需要返回所有元素,但是获取父节点,测试前一个元素是否有target元素,如果是,则返回target,但是如果它没有返回null元素的最后一个子id的{​​{1}}属性的值。

更新: xliff中有很多x,下面只是一个片段。我根据source元素(使用其trans-units属性)找到一个特定的元素,然后如果没有目标,我需要获取前一个节点的子节点。

以下是XML的片段,以便您了解我想要获得的内容:

<mrk mtype="seg" mid="6">

所以在这种情况下我希望mid返回。如果有目标,我应该<?xml version="1.0" encoding="utf-8"?> <xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0" version="1.2" sdl:version="1.0" xmlns="urn:oasis:names:tc:xliff:document:1.2"> <!-- xliff goes on here --> <trans-unit id="495bbe35-ad63-4d37-91e0-8261c2e4052e" translate="no"> <source> <x id="11" /> <x id="12" /> <!-- THIS IS THE ID I WANT TO GET --> </source> </trans-unit> <trans-unit id="5bccf5f4-56c9-4969-8416-f3114eb36e86"> <source> <x id="13" />SOME TEXT </source> <seg-source> <mrk mtype="seg" mid="6"> <!-- THIS IS THE MID I WANT TO START FROM --> <x id="13" />SOME TEXT </mrk> </seg-source> <target> <mrk mtype="seg" mid="6"> <x id="13" />SOME TRANSLATION </mrk> </target> <sdl:seg-defs> <sdl:seg id="6" conf="ApprovedTranslation" origin="interactive" /> </sdl:seg-defs> </trans-unit>

我设法使用以下代码行返回整个节点,但我似乎无法找到孩子们:

"12"

这会返回上一个节点,但随后代码进一步推进,我有了这个,但这引发了异常:

null

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

这有效

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement xliff = (XElement)doc.FirstNode;
            XNamespace ns = xliff.Name.Namespace;
            var testid = xliff.Descendants(ns + "trans-unit")
                .Where(x => x.Element(ns + "target") == null)
                .Descendants(ns + "x")
                .Select(y => y.Attribute("id").Value)
                .Last();

        }
    }
}

答案 1 :(得分:0)

我终于提出了以下代码,它完全符合我的要求,但我认为应该采用更流畅的方式来实现LINQ:

XElement testid = xliff.Descendants()
                       .Elements(xmlns + "trans-unit")
                       .Elements(xmlns + "seg-source")
                       .Elements(xmlns + "mrk")
                       .Where(e => e.Attribute("mtype").Value == "seg" && e.Attribute("mid").Value == SegId).FirstOrDefault();

if (testid.Parent.Parent.PreviousNode.ToString().IndexOf("<target>") > 0)
{
    return null;
}
else
{
    var strid = xliff.Descendants()
                     .Select(e => testid.Parent.Parent.PreviousNode as XElement)
                     .Elements(xmlns + "source")
                     .Elements(xmlns + "x")
                     .LastOrDefault()
                     .Attribute("id")
                     .Value.ToString();
     return strid;
 }