【发布时间】:2015-12-14 00:23:34
【问题描述】:
只有当值不为空时,我才尝试将属性添加到某个元素。我知道我可以使用模板和选择器来提供元素的静态版本,因此不需要 xsl:if,但我有 10 多个元素并且不想创建所有可能的排列。
可能仍然可以使用模板,如果可能的话,那将是理想的。如果没有,我可以使用 xsl:if。
源 XML:
<Test>
<Attribute1>A</Attribute1>
<Attribute3>B</Attribute3>
</Test>
使用以下 XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="Test">
<xsl:element name="MyElement">
<xsl:attribute name="FirstAttribute">
<xsl:value-of select="Attribute1"/>
</xsl:attribute>
<xsl:attribute name="SecondAttribute">
<xsl:value-of select="Attribute2"/>
</xsl:attribute>
<xsl:attribute name="ThirdAttribute">
<xsl:value-of select="Attribute3"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我得到一个如下所示的输出:
<MyElement FirstAttribute="A" SecondAttribute="" ThirdAttribute="B" />
但我想要这个:
<MyElement FirstAttribute="A" ThirdAttribute="B" />
我原本想使用这种模板:
<xsl:element name="MyElement">
<xsl:if test="Attribute1 != ''">
<xsl:attribute name="FirstAttribute">
<xsl:value-of select="Attribute1"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="Attribute2 != ''">
<xsl:attribute name="SecondAttribute">
<xsl:value-of select="Attribute2"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="Attribute3 != ''">
<xsl:attribute name="ThirdAttribute">
<xsl:value-of select="Attribute3"/>
</xsl:attribute>
</xsl:if>
</xsl:element>
很遗憾,这会导致以下错误:
XslTransformException was unhandled by user code
Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added.
当我使用这个 C# 代码来处理它时:
namespace XslTest
{
using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
class Program
{
private const string xmlSrcPath = "testXml.xml";
private const string xslPath = "testXsl.xsl";
static void Main(string[] args)
{
var result = Serialize(xmlSrcPath, xslPath);
Console.WriteLine(result);
Console.ReadLine();
}
private static string Serialize(string xmlFile, string xslTemplate)
{
var xmlMemoryStream = new MemoryStream();
var xmlFileStream = new FileStream(xmlFile, FileMode.Open);
xmlFileStream.CopyTo(xmlMemoryStream);
xmlMemoryStream.Flush();
xmlMemoryStream.Seek(0, SeekOrigin.Begin);
var xPathDoc = new XPathDocument(xmlMemoryStream);
var xslCompiledTransform = new XslCompiledTransform();
var transformedMemoryStream = new MemoryStream();
xslCompiledTransform.Load(xslTemplate);
var transformedWriter = new XmlTextWriter(transformedMemoryStream, null);
xslCompiledTransform.Transform(xPathDoc, transformedWriter);
transformedMemoryStream.Seek(0, SeekOrigin.Begin);
var transformedReader = new StreamReader(transformedMemoryStream);
return transformedReader.ReadToEnd();
}
}
}
有没有办法做这种操作?
【问题讨论】:
-
您必须编写一个恒等变换(将所有输入复制到输出)并在复制节点时进行修改。
-
我认为您没有显示导致错误的代码。问题是在为给定元素编写非属性节点后无法添加属性。因此,请确保先写入所有属性,然后再写入内容。
-
请提供一个可重现的示例 - 请参阅:stackoverflow.com/help/mcve。 --- “我有 10 多个元素,并且不想创建所有可能的排列。”我怀疑您可以在这里使用单个模板,而不是 10 多个
xsl:if系列语句。但是我们也需要对这个问题有一个更清晰的定义。 -
您仍然没有提供可重现的示例。仅使用您的代码,没有错误 - 请参阅:xsltransform.net/94rmq6q
-
看来我可能错误地识别了问题的根本原因并在简化代码时将其删除。我会努力解决这个问题,回家后找到根本原因。