Преобразование XSLT из XML в CSV для доступа к вложенным элементам с тем же именем
Я пытаюсь преобразовать приведенный ниже образец XML в CSV, но у меня возникают трудности с сопоставлением вложенных элементов с тем же именем (Правило).
Какое преобразование XSLT может генерировать эту структуру?
Файл @ path = "filename1.txt" | Правило @ id = "3.1.6" | Сообщение @ severity = "3" | Сообщение @ text = "3480. ....."
Файл @ path = "filename1.txt" | Правило @ id = "3.5.19" | Сообщение @ severity = "3" | Сообщение @ text = "1281. ....."
Файл @ path = "filename2.txt" | Правило @ id = "3.1.6" | Сообщение @ severity = "3" | Сообщение @ text = "3480. ....."
Файл @ path = "filename2.txt" | Правило @ id = "3.5.3" | Сообщение @ severity = "3" | Сообщение @ text = "3219. ....."
Путь будет выглядеть так:
AnalysisData\dataroot type="per-file"\File\tree type="rules"\RuleGroup name="MISRA_C"\...\Rule id="[1-9]+\.[1-9]+\.[1-9]+"\Message
Входной XML:
<AnalysisData>
<dataroot type="project">
</dataroot>
<dataroot type="per-file">
<File path="filename1.txt">
<Json>1.json</Json>
<tree type="rules">
<RuleGroup name="MISRA_C" total="2" active="2" >
<Rule id="3" total="2" active="2" text="Mandatory" >
<Rule id="3.1" total="1" active="1" text="Common" >
<Rule id="3.1.6" total="1" active="1" text="Declarations and definitions" >
<Message guid="qac-9.6.0-3480" total="1" active="1" severity="3" text="3480. Object/function '%s', with internal linkage, has been defined in a header file." />
</Rule>
</Rule>
<Rule id="3.5" total="1" active="1" text="MISRA Required Rules" >
<Rule id="3.5.19" total="1" active="1" text="M3CM Rule-7.2 A "u" or "U" suffix shall be applied to all integer constants that are represented in an unsigned type" >
<Message guid="qac-9.6.0-1281" total="1" active="1" severity="3" text="1281. Integer literal constant is of an unsigned type but does not include a "U" suffix." />
</Rule>
</Rule>
</Rule>
</RuleGroup>
</tree>
</File>
<File path="filename2.txt">
<Json>2.json</Json>
<tree type="rules">
<RuleGroup name="CrossModuleAnalysis" total="11" active="11" >
<Rule id="1" total="11" active="11" text="Maintainability" >
<Rule id="1.1" total="11" active="11" text="CMA Declaration Standards" >
<Message guid="rcma-2.0.0-1534" total="11" active="11" severity="2" text="1534. The macro '%1s' is declared but not used within this project." />
</Rule>
</Rule>
</RuleGroup>
<RuleGroup name="MISRA_C" total="36" active="16" >
<Rule id="3" total="20" active="0" text="Mandatory" >
<Rule id="3.1" total="12" active="0" text="Common" >
<Rule id="3.1.6" total="12" active="0" text="Declarations and definitions" >
<Message guid="qac-9.6.0-3480" total="12" active="0" severity="3" text="3480. Object/function '%s', with internal linkage, has been defined in a header file." />
</Rule>
</Rule>
<Rule id="3.5" total="8" active="0" text="MISRA Required Rules" >
<Rule id="3.5.3" total="8" active="0" text="M3CM Rule-2.1 A project shall not contain unreachable code" >
<Message guid="qac-9.6.0-3219" total="8" active="0" severity="3" text="3219. Static function '%s()' is not used within this translation unit." />
</Rule>
</Rule>
</Rule>
<Rule id="2" total="16" active="16" text="Minor" >
<Rule id="2.1" total="16" active="16" text="Common" >
<Rule id="2.1.15" total="16" active="16" text="Declarations and Definitions" >
<Message guid="qac-9.6.0-3227" total="16" active="16" severity="2" text="3227. The parameter '%s' is never modified and so it could be declared with the 'const' qualifier." />
</Rule>
</Rule>
</Rule>
</RuleGroup>
</tree>
</File>
</dataroot>
</AnalysisData>
1 ответ
Обычно я предлагаю написать шаблон для элемента, отображаемого в строке, а затем использовать
xsl:value-of separator
чтобы вывести строку с выбранным разделителем:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="text"/>
<xsl:template match="/" name="xsl:initial-template">
<xsl:apply-templates
select="/AnalysisData/dataroot[@type = 'per-file']/File/tree/RuleGroup[@name = 'MISRA_C']//Rule[Message]"/>
</xsl:template>
<xsl:template match="Rule">
<xsl:value-of select="ancestor::File/@path, @id, Message!(@severity, @text)" separator=" | "/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
Если вы хотите вывести значения атрибутов плюс имя элемента / атрибута, тогда может оказаться полезной функция:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="text"/>
<xsl:function name="mf:line" as="xs:string*">
<xsl:param name="atts" as="attribute()*"/>
<xsl:sequence
select="$atts ! (local-name(..) || '@' || local-name() || '="' || . || '"')"/>
</xsl:function>
<xsl:template match="/" name="xsl:initial-template">
<xsl:apply-templates
select="/AnalysisData/dataroot[@type = 'per-file']/File/tree/RuleGroup[@name = 'MISRA_C']//Rule[Message]"/>
</xsl:template>
<xsl:template match="Rule">
<xsl:value-of select="mf:line((ancestor::File/@path, @id, Message!(@severity, @text)))" separator=" | "/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>