我想制作一個 xslt 模板,它將逗號分隔的字串放入 CSV 中的每一行。
我目前的 xslt 如下供參考。我從我的 Person 類獲取資訊沒有任何問題,但至于 Item,我需要從變數中獲取,并且下面的“Item”模板不正確。而且我不能使用 tokenize,因為我的 xslt 版本是 1。
Id、Name 和 Address 可以從 C# 中的 Person 類中獲取。ItemValue 是一個單獨的變數。人數計數和ItemValue計數是計數的。即使計數不匹配,ItemValue 也可以保留為空。因為我無法將新變數附加到退出的人員類。
xml 可能看起來像這樣。
<PersonList>
<Person>
<ID>1</ID>
<Name>Name1</Name>
<Address>Add1</Address>
</Person>
<Person>
<ID>2</ID>
<Name>Name2</Name>
<Address>Add2</Address>
</Person>
<Person>
<ID>3</ID>
<Name>Name3</Name>
<Address>Add3</Address>
</Person>
<Person>
<ID>4</ID>
<Name>Name4</Name>
<Address>Add4</Address>
</Person>
<PersonList>
我預期的 csv 和 xml 如下所示。

<PersonList>
<Person>
<ID>1</ID>
<Name>Name1</Name>
<Address>Add1</Address>
<ItemValue>item1</ItemValue>
</Person>
<Person>
<ID>2</ID>
<Name>Name2</Name>
<Address>Add2</Address>
<ItemValue>item2</ItemValue>
</Person>
<Person>
<ID>3</ID>
<Name>Name3</Name>
<Address>Add3</Address>
<ItemValue>item3</ItemValue>
</Person>
<Person>
<ID>4</ID>
<Name>Name4</Name>
<Address>Add4</Address>
<ItemValue>item4</ItemValue>
</Person>
<PersonList>
以下是當前的 xslt。我沒有添加任何 xml 標簽,因為我想要的輸出是 csv 格式。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:param name="items">
<xsl:text>item1,item2,item3,item4</xsl:text>
</xsl:param>
<xsl:template name="Header" match="/">
<xsl:text>Id</xsl:text>
<xsl:text>,</xsl:text>
<xsl:text>Name</xsl:text>
<xsl:text>,</xsl:text>
<xsl:text>Address</xsl:text>
<xsl:text>,</xsl:text>
<xsl:text>ItemValue</xsl:text>
<xsl:text> </xsl:text>
<xsl:apply-templates select="//Person" />
</xsl:template>
<xsl:template match="Person">
<xsl:value-of select="@Id" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@Name" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@Address" />
<xsl:text>,</xsl:text>
<xsl:apply-templates select="//Item">
<xsl:with-param name="Person" select="." />
</xsl:apply-templates>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="Item">
<xsl:variable name="itemList" select="substring-before(concat($items, ','), ',')" />
<xsl:for-each select="$itemList">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
uj5u.com熱心網友回復:
您可以處理此問題的一種方法是調整我在評論中鏈接到的解決方案,如下所示:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:param name="items">item1,item2,item3,item4</xsl:param>
<xsl:template match="/PersonList">
<!-- header -->
<xsl:text>Id,Name,Adress,ItemValue </xsl:text>
<!-- data -->
<xsl:for-each select="Person">
<xsl:value-of select="ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Name"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Address"/>
<xsl:text>,</xsl:text>
<xsl:call-template name="get-Nth-value">
<xsl:with-param name="list" select="$items"/>
<xsl:with-param name="N" select="position()"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<!-- recursive call -->
</xsl:for-each>
</xsl:template>
<xsl:template name="get-Nth-value">
<xsl:param name="list"/>
<xsl:param name="N"/>
<xsl:param name="delimiter" select="','"/>
<xsl:choose>
<xsl:when test="$N = 1">
<xsl:value-of select="substring-before(concat($list, $delimiter), $delimiter)"/>
</xsl:when>
<xsl:when test="contains($list, $delimiter) and $N > 1">
<!-- recursive call -->
<xsl:call-template name="get-Nth-value">
<xsl:with-param name="list" select="substring-after($list, $delimiter)"/>
<xsl:with-param name="N" select="$N - 1"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
當應用于您的示例輸入時(糾正格式正確!),這將回傳:
結果
Id,Name,Adress,ItemValue
1,Name1,Add1,item1
2,Name2,Add2,item2
3,Name3,Add3,item3
4,Name4,Add4,item4
但是,最好通過$items并行處理 XML 和引數來減少所需的迭代次數:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:param name="items">item1,item2,item3,item4</xsl:param>
<xsl:template match="/PersonList">
<!-- header -->
<xsl:text>Id,Name,Adress,ItemValue </xsl:text>
<!-- data -->
<xsl:call-template name="generate-rows">
<xsl:with-param name="persons" select="Person"/>
<xsl:with-param name="items" select="$items"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="persons"/>
<xsl:param name="items"/>
<xsl:param name="delimiter">,</xsl:param>
<xsl:if test="$persons">
<xsl:variable name="person" select="$persons[1]" />
<!-- write to output -->
<xsl:value-of select="$person/ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$person/Name"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$person/Address"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="substring-before(concat($items, $delimiter), $delimiter)"/>
<xsl:text> </xsl:text>
<!-- recursive call -->
<xsl:call-template name="generate-rows">
<xsl:with-param name="persons" select="$persons[position() > 1]"/>
<xsl:with-param name="items" select="substring-after($items, $delimiter)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
請注意,這假定$items引數值是在運行時提供的。如果它可以被硬編碼,那么解決方案可能會簡單得多。
而且我們仍然不知道當物品的數量不等于人數時會發生什么。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/495854.html
上一篇:使用Saxon=錯誤將XML轉換為CSV:輸出字符160
下一篇:如何隱藏依賴的Nuget包?
