我为此道歉,因为周围有类似的问题,但是我试图应用所有这些并且不能让我使用现有的样式表html输出。
我有一个现有的XML和一个具有HTML标记的现有XSLT。
我只想使用XSLT向我的XML根节点添加属性,但仍然输出XSLT HTML。
我该怎么做?
我的XML :(我想在节点中添加xmlns属性:“StockList”)
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="do_it.xsl"?>
<StockList>
<StockItem>
<Item>AX123</Item>
<Description>Firetruck</Description>
<Count>500</Count>
<Order>No</Order>
</StockItem>
</StockList>
我的XSLT:(do_it.xsl)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:aa="http://www.w3schools.com/MMMXXX">
<xsl:template match="/">
<html>
<body>
<h2>Things On The Shelf:</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Item Code</th>
<th style="text-align:left">Item Description</th>
<th style="text-align:left">Current Count</th>
<th style="text-align:left">On Order?</th>
</tr>
<xsl:for-each select="aa:StockList/aa:StockItem">
<tr>
<td><xsl:value-of select="aa:Item"/></td>
<td><xsl:value-of select="aa:Description"/></td>
<td><xsl:value-of select="aa:Count"/></td>
<td><xsl:value-of select="aa:Order"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
那么我需要对XSLT做什么呢?我需要做什么呢?我尝试了大约15种不同的“应用模板”,但是当我设法添加属性时我不能添加我的html表吗? :(
请帮忙。
答案 0 :(得分:0)
这有一个XY problem的铃声。请放心,您无法通过XSLT更改源文档,即向其添加新属性,以便您的现有样式表代码可以正常工作。您也无法生成中间文档,然后通过XSLT 1.0对其进行转换(至少据我所知)。
你必须做以下两件事之一:
修改生成源XML的内容,以便正确地为您声明<StockList>
的命名空间。你可以这样做:
using (MemoryStream ms = new MemoryStream())
{
dataSet.WriteXml(ms);
ms.Position = 0; // reset!
XDocument xd = XDocument.Load(ms);
XNamespace aa = "http://www.w3schools.com/MMMXXX";
foreach (var el in xd.Root.DescendantsAndSelf())
{
el.Name = aa.GetName(el.Name.LocalName);
}
xd.Root.Add(new XAttribute(XNamespace.Xmlns + "aa", aa);
xd.Save(ms); // or just return the XDocument.ToString(), or return XDocument.CreateReader() as desired
}
修改您的XSLT,使其不关心命名空间。例如,将<xsl:for-each select="aa:StockList/aa:StockItem">
更改为<xsl:for-each select="*[local-name()='StockList']/*[local-name()='StockItem']">
,等等,只要您使用该命名空间前缀select
。这可能是更容易解决的问题 - 我自己也会使用这个解决方案。
答案 1 :(得分:0)
如果你想在一个样式表中使用XSLT 1.0应用两个转换,其中第一个添加命名空间(你需要将它添加到所有元素),第二个将第一个结果转换为HTML然后你需要执行使用变量作为结果树片段的一步,然后将该结果树片段转换为应用for-each
或其他模板的节点集。使用EXSLT扩展函数exsl:node-set
(http://exslt.org/exsl/functions/node-set/index.html)可以使用大多数XSLT处理器将结果树片段转换为节点集,但是IE使用的MSXML不支持EXSLT函数,只有类似的函数在不同的命名空间中。使用ms:script
扩展元素it is however possible to have MSXML support exsl:node-set
,完成两个转换的样式表看起来像
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aa="http://example.com/ns1"
xmlns:exsl="http://exslt.org/common"
xmlns:ms="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="aa exsl ms"
version="1.0">
<ms:script language="JScript" implements-prefix="exsl">
this['node-set'] = function(nodeList) {
return nodeList;
}
</ms:script>
<xsl:variable name="rtf1">
<xsl:apply-templates mode="add-namespace"/>
</xsl:variable>
<xsl:template match="*" mode="add-namespace">
<xsl:element name="aa:{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates mode="add-namespace"/>
</xsl:element>
</xsl:template>
<xsl:template match="/">
<html>
<body>
<h2>Things On The Shelf:</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Item Code</th>
<th style="text-align:left">Item Description</th>
<th style="text-align:left">Current Count</th>
<th style="text-align:left">On Order?</th>
</tr>
<xsl:for-each select="exsl:node-set($rtf1)/aa:StockList/aa:StockItem">
<tr>
<td><xsl:value-of select="aa:Item"/></td>
<td><xsl:value-of select="aa:Description"/></td>
<td><xsl:value-of select="aa:Count"/></td>
<td><xsl:value-of select="aa:Order"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
该示例分别在http://home.arcor.de/martin.honnen/xslt/test2015100701.xml http://home.arcor.de/martin.honnen/xslt/test2015100701.xsl处联机。
在Windows 10上与当前版本的Firefox,Chrome和IE一起工作。不幸的是,Microsoft Edge抱怨XSLT中的错误,我不确定是什么原因导致这种情况,因为像IE 11这样的Edge使用MSXML 6来执行XSLT。为了使它与Edge一起使用,我重写了样式表,不使用ms:script
而是使用function-available
和xsl:when
:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aa="http://example.com/ns1"
xmlns:exsl="http://exslt.org/common"
xmlns:ms="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="aa exsl ms"
version="1.0">
<xsl:variable name="rtf1">
<xsl:apply-templates mode="add-namespace"/>
</xsl:variable>
<xsl:template match="*" mode="add-namespace">
<xsl:element name="aa:{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates mode="add-namespace"/>
</xsl:element>
</xsl:template>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="function-available('exsl:node-set')">
<xsl:apply-templates select="exsl:node-set($rtf1)/aa:StockList"/>
</xsl:when>
<xsl:when test="function-available('ms:node-set')">
<xsl:apply-templates select="ms:node-set($rtf1)/aa:StockList"/>
</xsl:when>
<xsl:otherwise>
<html>
<body>
<p>Your XSLT processor does not support exsl:node-set or ms:node-set.</p>
</body>
</html>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/aa:StockList">
<html>
<body>
<h2>Things On The Shelf:</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Item Code</th>
<th style="text-align:left">Item Description</th>
<th style="text-align:left">Current Count</th>
<th style="text-align:left">On Order?</th>
</tr>
<xsl:for-each select="aa:StockItem">
<tr>
<td><xsl:value-of select="aa:Item"/></td>
<td><xsl:value-of select="aa:Description"/></td>
<td><xsl:value-of select="aa:Count"/></td>
<td><xsl:value-of select="aa:Order"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
当然,这也适用于Firefox,Chrome和IE。