如何使用 XSLT 复制 XML 以生成相同形式的另一个新 XML
Posted
技术标签:
【中文标题】如何使用 XSLT 复制 XML 以生成相同形式的另一个新 XML【英文标题】:How to copy an XML using XSLT to produce another new XML of the same form 【发布时间】:2018-03-04 18:49:48 【问题描述】:在使用 XSLT 对 XML 文档执行 3 级排序之后。我无法复制已排序的 xml。我的原始 XML 是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<Test>
<TestPhase>5</TestPhase>
<TestFlow>9</TestFlow>
<TestParameter>5</TestParameter>
</Test>
<Test>
<TestPhase>5</TestPhase>
<TestFlow>9</TestFlow>
<TestParameter>2</TestParameter>
</Test>
<Test>
<TestPhase>1</TestPhase>
<TestFlow>3</TestFlow>
<TestParameter>1</TestParameter>
</Test>
<Test>
<TestPhase>1</TestPhase>
<TestFlow>2</TestFlow>
<TestParameter>2</TestParameter>
</Test>
<Test>
<TestPhase>2</TestPhase>
<TestFlow>4</TestFlow>
<TestParameter>6</TestParameter>
</Test>
<Test>
<TestPhase>2</TestPhase>
<TestFlow>4</TestFlow>
<TestParameter>1</TestParameter>
</Test>
<Test>
<TestPhase>2</TestPhase>
<TestFlow>2</TestFlow>
<TestParameter>10</TestParameter>
</Test>
<Test>
<TestPhase>2</TestPhase>
<TestFlow>2</TestFlow>
<TestParameter>1</TestParameter>
</Test>
.
.
.
.
.
</Root>
3级排序后,我复制了一份。但新的 XML (test.xml) 似乎如下:
<Test><TestPhase>3</TestPhase><TestFlow>2</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>3</TestPhase><TestFlow>2</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>4</TestPhase><TestFlow>1</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>4</TestPhase><TestFlow>1</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>4</TestPhase><TestFlow>2</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>4</TestPhase><TestFlow>2</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>5</TestPhase><TestFlow>1</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>5</TestPhase><TestFlow>1</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>5</TestPhase><TestFlow>2</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>5</TestPhase><TestFlow>2</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>6</TestPhase><TestFlow>1</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>6</TestPhase><TestFlow>1</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>6</TestPhase><TestFlow>2</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>6</TestPhase><TestFlow>2</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>7</TestPhase><TestFlow>1</TestFlow><TestParameter>1</TestParameter></Test><Test><TestPhase>7</TestPhase><TestFlow>1</TestFlow><TestParameter>2</TestParameter></Test><Test><TestPhase>7</TestPhase><TestFlow>2</TestFlow><TestParameter>1</TestParameter></Test><Test>< .
.
.
.
.
请在这方面给我建议。我是 XPath / XSLT 的新手。我的 XSLT 是这样写的:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Root">
<xsl:apply-templates>
<xsl:sort select="TestPhase" data-type="number" order="ascending"/>
<xsl:sort select="TestFlow" data-type="number" order="ascending"/>
<xsl:sort select="TestParameter" data-type="number" order="ascending"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我还检查了我的代码,方法是只复制原始 XML,而不对其进行排序。出现同样的问题。我尝试了以下 XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这个词:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
虽然我正在使用,但没有出现在第一行
<xsl:output method="xml" indent="yes"/>
尽管我选择了,但一切都崩溃了:
indent="yes"
请帮忙。非常感谢您的帮助。
谢谢。
干杯:)
【问题讨论】:
您实际上是如何执行 XSLT 转换的?您使用的是什么 XSLT 处理器?请注意,缩进(或缺少)实际上并不是由 XSLT 进程本身完成的,而是由将结果序列化为字符串的东西完成的。 【参考方案1】:首先,您所指的“词”是 xml 声明。要将其包含在您的输出中,您应该将“omit-xml-declaration”添加到 xsl:output
语句(如果您希望将其包含在声明中,请与“standalone”一起)
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" standalone="yes" />
但是,这最初是行不通的,因为要使输出 XML 文档独立,它必须格式正确,只有一个根元素。您当前匹配 Root
的模板没有复制该元素。
此外,通过执行xsl:apply-templates
,您将选择Root
的所有子节点,但这包括空白节点,而不仅仅是Test
元素。要解决这个问题,您可以通过执行<xsl:apply-templates select="Test">
来明确选择Test
元素。或者,您可以通过将 <xsl:strip-space elements="*" />
添加到 XSLT 来从 XML 中删除仅空白节点。
试试这个 XSLT,例如:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" standalone="yes" />
<xsl:template match="Root">
<xsl:copy>
<xsl:apply-templates select="Test">
<xsl:sort select="TestPhase" data-type="number" order="ascending"/>
<xsl:sort select="TestFlow" data-type="number" order="ascending"/>
<xsl:sort select="TestParameter" data-type="number" order="ascending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
至于实际结果没有缩进,这取决于转换的结果是如何被序列化的。如果您使用的是 C#(我根据您之前提出的问题做出了这个假设),您可能需要检查是否将 xslt 输出设置传递给 XmlWriter。请参阅https://msdn.microsoft.com/en-us/library/system.xml.xsl.xslcompiledtransform.outputsettings(v=vs.110).aspx,它给出了这个例子:
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(stylesheet);
XPathDocument doc = new XPathDocument(filename);
XmlWriter writer = XmlWriter.Create(Console.Out, xslt.OutputSettings);
xslt.Transform(doc, writer);
writer.Close();
【讨论】:
非常感谢 Tim C。我终于能够生成带有缩进文档元素和声明的 XML。但是,仍然存在一个小缺陷,尽管我按照您的方法,但没有standalone="yes"。但是,非常感谢来自 newbuntu 的 Tim C. Cheers!以上是关于如何使用 XSLT 复制 XML 以生成相同形式的另一个新 XML的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 XSLT saxonica 将 xml 转换为点? [复制]