是否有用于可控XML格式的样式表或Windows命令行工具,特别是每行放置一个属性?

是否有用于可控XML格式的样式表或Windows命令行工具,特别是每行放置一个属性?,xml,pretty-print,xml-formatting,Xml,Pretty Print,Xml Formatting,我正在为Windows搜索一个XSLT或命令行工具(或可以制作成命令行工具的C#代码,等等),它可以进行XML漂亮的打印。具体地说,我想要一个能够将属性一对一地放在一行中的,类似于: <Node> <ChildNode value1='5' value2='6' value3='happy' /> </Node> 它不必完全像那样,但我想将它用于一个XML文件,该文件具有几十个属性的节点,并将它们分布在多行中,

我正在为Windows搜索一个XSLT或命令行工具(或可以制作成命令行工具的C#代码,等等),它可以进行XML漂亮的打印。具体地说,我想要一个能够将属性一对一地放在一行中的,类似于:

<Node>
   <ChildNode 
      value1='5'
      value2='6'
      value3='happy' />
</Node>

它不必完全像那样,但我想将它用于一个XML文件,该文件具有几十个属性的节点,并将它们分布在多行中,使它们更易于阅读、编辑和文本区分


注意:我认为我的首选解决方案是XSLT表,我可以通过C#方法传递,尽管Windows命令行工具也很好。

XMLNotepad2007可以手动执行此操作。。。让我看看能不能把它写成脚本

没有。。。它可以像这样启动它:

XmlNotepad.exe a.xml
剩下的只是单击save按钮。Power Shell,其他工具可以自动执行此操作。

只需使用以下xslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="ISO-8859-1"/>
  <xsl:param name="indent-increment" select="'   '"/>

  <xsl:template name="newline">
    <xsl:text disable-output-escaping="yes">
</xsl:text>
  </xsl:template>

  <xsl:template match="comment() | processing-instruction()">
    <xsl:param name="indent" select="''"/>
    <xsl:call-template name="newline"/>    
    <xsl:value-of select="$indent"/>
    <xsl:copy />
  </xsl:template>

  <xsl:template match="text()">
    <xsl:param name="indent" select="''"/>
    <xsl:call-template name="newline"/>    
    <xsl:value-of select="$indent"/>
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:template>

  <xsl:template match="text()[normalize-space(.)='']"/>

  <xsl:template match="*">
    <xsl:param name="indent" select="''"/>
    <xsl:call-template name="newline"/>    
    <xsl:value-of select="$indent"/>
      <xsl:choose>
       <xsl:when test="count(child::*) > 0">
        <xsl:copy>
         <xsl:copy-of select="@*"/>
         <xsl:apply-templates select="*|text()">
           <xsl:with-param name="indent" select="concat ($indent, $indent-increment)"/>
         </xsl:apply-templates>
         <xsl:call-template name="newline"/>
         <xsl:value-of select="$indent"/>
        </xsl:copy>
       </xsl:when>       
       <xsl:otherwise>
        <xsl:copy-of select="."/>
       </xsl:otherwise>
     </xsl:choose>
  </xsl:template>    
</xsl:stylesheet>


或者,作为另一个选项,这里有一个perl脚本:

有一个工具,可以将属性拆分为每行一个:。这是一个perl脚本,因此您必须安装它。用法:

您还可以通过创建名为attributeOrdering.txt的文件并调用
perl xmlpp.pl-s-t input.xml
来确定属性的顺序。有关更多选项,请使用
perl-xmlpp.pl-h


我希望,它没有太多的bug,但到目前为止,它对我很有效。

您可以实现一个简单的SAX应用程序,它将按原样复制所有内容,并按您喜欢的方式缩进属性

UPD

表示XML的
简单API
。它是XML解析的推送模型(Builder设计模式的经典示例)。该API存在于大多数当前开发平台中(尽管本机.Net类库缺少API,但有XMLReader intead)

这是一个python的原始实现,它相当神秘,但您可以实现其主要思想

从系统导入标准输出
从xml.sax导入解析
从xml.sax.handler导入ContentHandler
从xml.sax.saxutils导入转义
类MyHandler(ContentHandler):
定义初始化(自、文件、编码):
self.level=0
self.elem_缩进=“”
#下一个街区应该换行吗
self.\u allow\u N=False
#是否使用>(以允许/>)关闭开始标记
self.\u tag\u open=False
self.\u file=file_
自我编码=编码
定义写入(自身、字符串):
self.\u file.write(字符串编码(self.\u编码))
def startElement(自身、名称、属性):
如果self.\u tag\u打开:
self.\u写入(“>”)
self.\u tag\u open=False
如果自我允许:
self.\u写入('\n')
缩进=self.elem\u缩进*self.level
其他:
缩进=“”
自我写入(“%s”)
self.\u tag\u open=False
返回
如果自我允许:
self.\u写入('\n')
缩进=self.elem\u缩进*self.level
其他:
缩进=“”
自写入(“%s%”(缩进,名称))
self.\u allow\u N=True
def字符(自身、内容):
如果self.\u tag\u打开:
self.\u写入(“>”)
self.\u tag\u open=False
如果是content.strip():
self.\u allow\u N=False
自我书写(转义(内容))
其他:
self.\u allow\u N=True
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
parser=parse('test.xsl',MyHandler(stdout,stdout.encoding))
在SourceForge上再试一次。虽然它经常用于[X]HTML,但我以前在XML上成功地使用过它-请确保使用
-XML
选项

Tidy读取HTML、XHTML和XML文件,并写入已清理的标记。。。对于一般的XML文件,Tidy仅限于纠正基本的格式良好错误和漂亮的打印

人们已经将其移植到多个平台上,并将其作为可执行和可调用的库提供

Tidy拥有大量的功能,包括:

缩进属性
顶部类型:布尔值
默认值:无示例:是/否,是/否,t/f,对/错,1/0
此选项指定Tidy是否应在新行上开始每个属性

一个警告:

对XML的有限支持

符合W3C XML 1.0建议的XML处理器对接受哪些文件非常挑剔。Tidy可以帮助您修复导致XML文件被拒绝的错误。Tidy还不能识别所有XML功能,例如,它不理解CDATA部分或DTD子集

但我怀疑,除非您的XML真的很高级,否则该工具应该可以正常工作。

这里有一个小C#示例,它可以直接由您的代码使用,或者内置到exe中,并在命令行中作为“
myexe from.XML to.XML
”调用:

样本输入:

<Node><ChildNode value1='5' value2='6' value3='happy' /></Node>
请注意,如果您想要字符串而不是写入文件,只需使用
StringBuilder
交换即可:

StringBuilder sb = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(oldXml)))
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
    writer.WriteNode(reader, false);
    writer.Close();
}
string newXml = sb.ToString();

下面是一个PowerShell脚本。它接受以下输入:

<?xml version="1.0" encoding="utf-8"?>
<Node>
    <ChildNode value1="5" value2="6" value3="happy" />
</Node>
将该脚本另存为C:\formatxml.ps1。然后,在PowerShell提示符中键入以下内容:

C:\formatxml.ps1 C:\Path\To\UglyFile.xml C:\Path\To\NeatAndTidyFile.xml
该脚本基本上只使用.NET framework,因此您可以非常轻松地将其迁移到C#应用程序中

注意:如果您以前没有从PowerShell运行脚本,则必须在提升的PowerShell提示符下执行以下命令,然后才能执行脚本:

Set-ExecutionPolicy RemoteSigned
不过你只需要做一次


我希望这对你有用。

看起来不错。要完成这项工作,是否有命令行xslt处理器/我可以使用c#使用xslt处理XML吗?两者都有,但saxon命令行xslt处理器()应该足够了:)
<?xml version="1.0" encoding="utf-8"?>
<Node>
    <ChildNode value1="5" value2="6" value3="happy" />
</Node>
<?xml version="1.0" encoding="utf-8"?>
<Node>
  <ChildNode
    value1="5"
    value2="6"
    value3="happy" />
</Node>
param(
    [string] $inputFile = $(throw "Please enter an input file name"),
    [string] $outputFile = $(throw "Please supply an output file name")
)

$data = [xml](Get-Content $inputFile)

$xws = new-object System.Xml.XmlWriterSettings
$xws.Indent = $true
$xws.IndentChars = "  "
$xws.NewLineOnAttributes = $true

$data.Save([Xml.XmlWriter]::Create($outputFile, $xws))
C:\formatxml.ps1 C:\Path\To\UglyFile.xml C:\Path\To\NeatAndTidyFile.xml
Set-ExecutionPolicy RemoteSigned