【问题标题】:C# getting a specific attribute of a child of a Previous node in XML while testing the node for a missing elementC#在测试节点是否缺少元素时获取XML中Previous节点的子节点的特定属性
【发布时间】:2016-04-27 18:36:19
【问题描述】:

我有一个xliff,我正在尝试获取前一个trans-unitsource 的最后一个x 元素的id 属性的值,只要它没有@987654327 @孩子。

所以非常具体,我不只是需要返回所有元素,而是获取父节点,测试前一个是否有target元素,如果有则返回null,如果没有则返回source 元素的最后一个子元素 xid 属性的值。

更新: xliff 中有很多trans-units,下面只是一个sn-p。我根据<mrk mtype="seg" mid="6"> 元素(使用其mid 属性)找到一个特定的节点,然后如果没有目标,我需要获取前一个节点的子节点。

这是 XML 的 sn-p,因此您可以看到我想要得到的内容:

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

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

xliff = XDocument.Load(Path.GetFullPath(FilePath));
XNamespace xmlns = "urn:oasis:names:tc:xliff:document:1.2";
XNamespace ns = "http://sdl.com/FileTypes/SdlXliff/1.0";
string 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().Parent.Parent.PreviousNode.ToString();

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

string 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)
                    .Select(n => n.Parent.Parent.PreviousNode as XElement)
                    .Where(c => c.Elements(xmlns + "target") == null && c.Elements(xmlns + "source").Elements(xmlns + "x").Last().Value != null)
                    .FirstOrDefault().Attribute("id").Value;

有人可以帮忙吗?

【问题讨论】:

  • 谢谢。我也检查了这一点,我可以按照方向进行。查看代码更新,但我正在尝试实际测试之前的trans-unit 中是否没有target 元素,同时返回source 元素的最后一个子元素的id 属性。所以这个问题比仅仅返回所有元素更复杂。这已经完成了。

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


【解决方案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();

        }
    }
}

【讨论】:

  • 哇。谢谢你。就像我发布我的代码一样。我自然而然地对你的答案投了赞成票。我不清楚,但 xliff 中有很多这样的trans-units。我根据&lt;mrk mtype="seg" mid="6"&gt; 元素找到一个特定的元素,然后如果没有目标,我需要获取前一个节点的子节点。 (我编辑了问题以使其清楚。)
  • 意思是我有一个起点,从那里我必须向上导航到父节点到父节点到上一个节点。
【解决方案2】:

我终于想出了下面的代码,它完全符合我的要求,但我认为应该有一种更流畅的方式来使用 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;
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多