Сумма XSLT по значению поиска из другого файла
Я хочу получить общее количество конкретного ученика из следующих двух файлов XML:
--- Файл: mark.xml
----
<marks>
<mark type="HD">10</mark>
<mark type="D">8</mark>
<mark type="C">5</mark>
</marks>
--- Файл: studentRecord.xml
---
<students>
<student id="1234">
<grade>HD</grade>
</student>
<student id="1234">
<grade>C</grade>
</student>
<student id="1111">
<grade>D</grade>
</student>
</students>
Как я могу получить общий балл студента, имеющего id 1234
? это должно быть 15.
3 ответа
Вот краткое и простое решение XSLT (на самом деле это просто XPath):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output method="text"/>
<my:MarkValues>
<marks>
<mark type="HD">10</mark>
<mark type="D">8</mark>
<mark type="C">5</mark>
</marks>
</my:MarkValues>
<xsl:template match="/*">
<xsl:value-of select=
"sum(document('')/*
/my:MarkValues/*/*
[@type = current()/*
[@id='1234']/grade
]
)"/>
</xsl:template>
</xsl:stylesheet>
когда это преобразование применяется к предоставленному документу XML (с именем "studentRecord.xml"):
<students>
<student id="1234">
<grade>HD</grade>
</student>
<student id="1234">
<grade>C</grade>
</student>
<student id="1111">
<grade>D</grade>
</student>
</students>
желаемый ответ выдается:
15
Если вы хотите сохранить значения меток в отдельном файле (не включенном в таблицу стилей XSLT, как указано выше), выражение XPath должно быть слегка изменено (только аргумент document()
функция:
sum(document('mark.xml')/*/*
[@type = current()/*
[@id='1234']/grade
]
)
Пояснение:
Использование XSLT
document()
функция.Использование XSLT
current()
функция.Использование XPath
sum()
функция.
В следующем преобразовании я создаю сначала переменную с собранными значениями, а затем XPath sum()
Функция используется для получения результата. Это не так элегантно и умно, как подход @Dimitre, но я бы все равно хотел опубликовать:)
XSLT 2.0 протестирован под Saxon-HE 9.2.1.1J
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="lookup" select="document('lookup.xml')/marks"/>
<xsl:template match="students">
<xsl:variable name="values">
<values>
<xsl:for-each select="student[@id='1234']">
<value><xsl:value-of select="$lookup/mark[@type=current()/grade]"/></value>
</xsl:for-each>
</values>
</xsl:variable>
<xsl:value-of select="sum($values//value)"/>
</xsl:template>
</xsl:stylesheet>
Результат, примененный к входным данным, представленным в вопросе, является просто суммой:
15
Попробуйте этот код C#:
var studenst = XElement.Load("studentRecord.xml");
var marks= XElement.Load("marks.xml");
Dictionary<string, int> marksDic = new Dictionary<string, int>();
foreach (XElement m in marks.Descendants())
{
if (m.Attribute("type") != null)
marksDic.Add(m.Attribute("type").Value, int.Parse(m.Value));
}
foreach (XElement s in studenst.Descendants().Where(x=>(x.Attribute("id") !=null ?int.Parse(x.Attribute("id").Value):0)==id))
{
Console.WriteLine(marksDic.Where(x => x.Key == s.Value)
.Select(x => x.Value).Single());
}
}