使用"PreviousNode"解析C#LINQ xml; [英] C# LINQ xml parsing using "PreviousNode"
问题描述
在SO的帮助下,我设法整理了以下LINQ表达式.
With quite some help from SO, I managed to put together the following LINQ expression.
var parentids = xliff.Descendants()
.Elements(xmlns + "trans-unit")
.Elements(xmlns + "seg-source")
.Elements(xmlns + "mrk")
.Where(e => e.Attribute("mtype").Value == "seg")
.Select(item => (XElement)item.Parent.Parent.PreviousNode)
.Where(item => item != null)
.Select(item => item.Elements(xmlns + "source")
.Where(itema => itema != null)
.Select(itemb => itemb.Elements(xmlns + "x")
.LastOrDefault()
.Attribute("id")
.Value.ToString())).ToArray();
它的作用是找到一个mrk
标记(具有@mtype="seg"
),然后升至trans-unit
祖先(.parent.parent),并检查先前的同级trans-unit
是否具有子元素trans
,如果不是,则从source
子元素返回最后一个x
元素的@id
,否则返回null
(必须返回null,不能不返回匹配项).
What it does is that it locates a mrk
tag (that has @mtype="seg"
) and then it goes up to the trans-unit
ancestor (.parent.parent) and checks if the previous sibling trans-unit
has a child trans
and if not, it returns from the source
child the @id
of the last x
element, otherwise it returns null
(it must return null, cannot just not return match).
我需要补充一点,尽管下面的示例中只有一个这样的先前节点,没有trans
元素,但在现实生活中xml中还有很多,因此我必须使用PreviousNode
.
I need to add that while the below samples only have one such previous node with no trans
element, in the real life xml there are many more, so I must use PreviousNode
.
这是它可以使用的XML,并完美地返回"2"
:
Here is the XML it works with, and returns "2"
perfectly:
<?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">
<file original="Pasadena_Internet_2016.xml" source-language="en-US" datatype="x-sdlfilterframework2" target-language="da-DK">
<body>
<trans-unit id="d679cb2d-ecba-47ba-acb7-1bb4a798c755" translate="no">
<source>
<x id="0" />
<x id="1" />
<x id="2" />
</source>
</trans-unit>
<trans-unit id="aed9fde2-fd1b-4eba-bfc9-06d325aa7047">
<source>
<x id="3" />Pasadena, California’s iconic Colorado Boulevard <x id="4" />has been the site of the world-famous Tournament of Roses Parade since it began in 1890.
</source>
<seg-source>
<mrk mtype="seg" mid="1">
<x id="3" />Pasadena, California’s iconic Colorado Boulevard <x id="4" />has been the site of the world-famous Tournament of Roses Parade since it began in 1890.
</mrk>
</seg-source>
<target>
<mrk mtype="seg" mid="1">
<x id="3" /><x id="4" />Pasadena, Californiens ikoniske Colorado Boulevard har været stedet for den verdensberømte Rose Bowl-parade siden den begyndte i 1890.
</mrk>
</target>
</trans-unit>
</body>
</file>
</xliff>
问题是我需要解决的最后一步是存在另一种类型的XML,其注视trans-unit
封装在另一个XML中不存在的另一个group
元素中.因此,这里还有一个父级可以向上跳转并获得前一个trans-unit
兄弟姐妹,就在group
之前.
The problem is that I need to solve as a last step is that there is another type of XML that has the staring trans-unit
encapsulated within another group
element that is not present in the other XML. So here there is one more parent to jump upwards and get the previous trans-unit
sibling, right before the group
.
我正在尝试将其构建到相同的LINQ表达式中,以便它可以处理两种情况.
I am trying to build this into the same LINQ expression so it handles both scenarios.
实际上,如果我将第6行修改为此,那么它将起作用:
In fact if I modify the line 6 to this, then it works:
.Select(item => (XElement)item.Parent.Parent.Parent.PreviousNode)
<!-- ^------ additional Parent -->
这是另一个上面的代码现在引发异常的XML,但是它应该返回"0"
:
Here is the other XML that right now throws an exception with the above code, but it should return "0"
:
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2" sdl:version="1.0">
<file original="Internet_Anti-DrugIntro2015.xml_1457007.xlf" datatype="x-sdlfilterframework2" source-language="en-US" target-language="hu-HU">
<body>
<trans-unit translate="no" id="c3a13bfb-ed51-49cf-8278-e2c86c2114c0">
<source>
<x id="0"/>
</source>
</trans-unit>
<group>
<sdl:cxts>
<sdl:cxt id="1"/>
</sdl:cxts>
<trans-unit id="3b4520df-4483-4c9e-8a9b-ce2544269f3e">
<source>
<x id="1"/>
</source>
<seg-source>
<mrk mtype="seg" mid="2">
<x id="1"/>Drugs are robbing our children of their future.
</mrk>
<mrk mtype="seg" mid="3">
<x id="2"/>Every 17 seconds a teenager experiments with an illicit drug for the first time.
</mrk>
</seg-source>
<target>
<mrk mtype="seg" mid="2">
<x id="1"/>A drogok megfosztják gyermekeinket a jövőjüktől.
</mrk>
<mrk mtype="seg" mid="3">
<x id="2"/>17 másodpercenként egy újabb tizenéves próbálja ki először a kábítószereket.
</mrk>
</target>
</trans-unit>
</group>
<trans-unit translate="no" id="7890462c-edcb-4fe6-9192-033ba76d9942">
<source>
<x id="183"/>
</source>
</trans-unit>
</body>
</file>
</xliff>
我将不胜感激任何帮助.
I will be more than appreciative for any help.
推荐答案
您可以尝试使用Ancestors().Last()
查找名为的最高级别祖先,而不是根据XML结构多次使用Parent
导航XML树. "trans-unit"
或"group"
,然后导航到上一个节点.
Instead of navigating up the XML tree using Parent
several times depending on the XML structure, you can try using Ancestors().Last()
to find the highest level ancestor named either "trans-unit"
or "group"
, and then navigate to the previous node.
尝试替换此部分:
.Select(item => (XElement) item.Parent.Parent.PreviousNode)
与此:
.Select(item => (XElement)item.Ancestors()
.Last(o => new[]{"trans-unit","group"}.Contains(o.Name.LocalName))
.PreviousNode)
这篇关于使用"PreviousNode"解析C#LINQ xml;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!