【问题标题】:Reformat xml file using xslt and retain exact formatting使用 xslt 重新格式化 xml 文件并保留准确的格式
【发布时间】:2016-04-03 11:21:17
【问题描述】:

我有一个 xml 文件,需要以特定方式格式化以确保可读性。

源 XML

<?xml version="1.0" encoding="UTF-8"?>
<facility>
 <attributes>
   <id>1</id>
   <name>Facility Name</name>
   <coordinate>Lat,Long</coordinate>
   <projection>mercator</projection>
   <units>imperial</units>
   <showcart>yes</showcart>
   <shotplanner>yes</shotplanner>
   <sound>on</sound>
   <gfbkgcolor>#ff0000</gfbkgcolor>
   <gftxtcolor>#ffffff</gftxtcolor>
   <gcbkgcolor>#ffffff</gcbkgcolor>
   <gctxtcolor>#000000</gctxtcolor>
 </attributes>
</facility>

预期输出

<facility name="Facility Name" id="1" 
          coordinate="Lat,Long" projection="mercator" 
          units="imperial" showcart="yes" shotplanner="yes" 
          sound="on" gfbkgcolor="#ff0000" gftxtcolor="#ffffff" 
          gcbkgcolor="#ffffff">
</facility>

我有一个复杂的 xml 文件,但这就是我想要做的。

XSL 模板

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <xsl:for-each select="facility/attributes">
        <facility id="{id}" name="{name}" 
                  coordinate="{coordinate}">
        </facility>
         <xsl:text>&#xA;</xsl:text>
        <test>"hello"</test>
   </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

使用这个&lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt; 似乎会引发错误并且不显示输出xml。

  1. 是否可以在使用 xsl 的某些属性后进行换行?
  2. 我可以在给定元素中的子元素之间设置换行符吗(这样可以对它们进行逻辑分组)?

我正在通过 php 形成上述 xml。一旦我有了 xml,我希望它按照上面提到的格式进行格式化。我可以使用 php 字符串来做到这一点,但它是一个巨大的文件,这样做会很乏味。可以用xsl来解决这个问题吗?

任何关于如何实现这一点的指针将不胜感激。谢谢

【问题讨论】:

  • 您需要了解 XSLT 的处理模型采用输入树并将其转换为具有元素节点和属性节点的结果树,而属性的任何格式以及它们之间的空间都是可选的序列化创建结果树之后的步骤。因此,某些属性之间的换行符不是 XSLT 转换创建的,而是序列化的一部分。并且 XSLT 1.0 定义的序列化选项不提供任何属性之间的换行设置。
  • 那么实现该输出的唯一方法是使用具有正确格式的 php 将其写入文件?
  • 要将attributes 元素的子元素转换为属性,您可以优雅地使用XSLT,但要强制执行特定格式的属性,您需要查看XSLT 处理器的序列化选项或自己实现序列化,在 PHP 或 XSLT 中(如 lenzconsulting.com/xml-to-string)。

标签: php xml xslt formatting line-breaks


【解决方案1】:

我不知道有任何 XML 序列化程序(基于 XSLT 或其他)可以让您对一组属性的格式进行这种级别的控制,尽管您可能会通过利用撒克逊语来接近撒克逊语: xsl:output 上的属性顺序和 saxon:line-length 属性:参见 http://www.saxonica.com/documentation/index.html#!extensions/output-extras/serialization-parameters

目前尚不清楚为什么您当前的代码会引发错误,但由于您没有告诉我们错误是什么,因此我不会尝试回答这部分问题。

【讨论】:

    【解决方案2】:

    由于 PHP 是一种通用语言并配备了 XSLT 1.0 处理器,您可以在一个脚本中处理 xml 转换和文本格式化这两种操作:

    XSLT 脚本(保存外部以在下面加载或使用 loadXML() 作为嵌入字符串添加)

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>
    
      <!-- Identity Transform -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="attributes/*"/>
        </xsl:copy>
      </xsl:template>  
    
      <!-- Migrate Nodes to Attributes -->
      <xsl:template match="attributes/*">    
          <xsl:attribute name="{name()}">
            <xsl:value-of select="."/>
          </xsl:attribute>
      </xsl:template>
    
    </xsl:transform>
    

    PHP脚本

    <?php
    
    // Load the XML source and XSLT file
    $doc = new DOMDocument();
    $doc->load('Source.xml');
    
    $xsl = new DOMDocument;
    $xsl->load('XSLTScript.xsl');
    
    // Configure the processor
    $proc = new XSLTProcessor;
    $proc->importStyleSheet($xsl); 
    
    // Transform XML source
    $newXml = $proc->transformToXML($doc);
    
    // Add line breaks, tabs, and spaces between attributes to output string
    $newXml = str_replace("coordinate", "\n\t\t  coordinate", $newXml);
    $newXml = str_replace("units", "\n\t\t  units", $newXml);
    $newXml = str_replace("sound", "\n\t\t  sound", $newXml);
    $newXml = str_replace("gcbkgcolor", "\n\t\t  gcbkgcolor", $newXml);
    $newXml = str_replace("/>", ">\n</facility>", $newXml);
    
    echo $newXml;
    
    // Save output to file
    $xmlfile = 'Output.xml';
    file_put_contents($xmlfile, $newXml);
    
    ?>
    

    输出

    <?xml version="1.0" encoding="UTF-8"?>
    <facility id="1" name="Facility Name" 
              coordinate="Lat,Long" projection="mercator" 
              units="imperial" showcart="yes" shotplanner="yes" 
              sound="on" gfbkgcolor="#ff0000" gftxtcolor="#ffffff" 
              gcbkgcolor="#ffffff" gctxtcolor="#000000">
    </facility>
    

    【讨论】:

    • 您在那里所做的非常好,我最终通过 php 完成了它,因为无论如何我的源代码是一个 php 数组。发布我所做的事情的 sn-p。
    【解决方案3】:

    <?php
    
    public function writeToXml(){
    		$data = array(
    			"id"          => 15,
    			"name"        => "Facility Name",
    			"coordinate"  => "Lat,lon",
    			"projection"  => "mercator",
    			"units"       => "imperial",
    			"showcart"    => "yes",
    			"shotplanner" => "yes",
    			"sound"       => "on",
    			"gfbkgcolor"  => "#ff0000",
    			"gftxtcolor"  => "#ffffff",
    			"gcbkgcolor"  => "#ffffff",
    			"gctxtcolor"  => "#000000",
    			"gbbkgcolor"  => "#0000ff",
    			"gbtxtcolor"  => "#ffffff"
    		);
    
        // Inserts a new line with a specified indent
    	function insertNewLine($indent = 0){
    		$line = "\n";
    		$line .= str_repeat("\t", $indent);
    		return $line;
    	}
        
        // Formats a given string with a trailing space
    	function formatString($string) {
    		$data = "\"" . $string . "\" ";
    		return $data;
    	}
    
    	$facility = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
    	$facility .= insertNewLine();
    	$facility .= "<facility name=" . formatString($data['name']);
    	$facility .= "coordinate=" . formatString($data["coordinate"]);
    	$facility .= insertNewLine(1);
    	$facility .= "projection=" . formatString($data['projection']);
    	$facility .= "units=" . formatString($data['units']);
    	$facility .= "showcart=" . formatString($data['showcart']);
    	$facility .= "shotplanner=" . formatString($data['shotplanner']);
    	$facility .= "sound=" . formatString($data['sound']);
    	$facility .= insertNewLine(1);
    	$facility .= "gfbkgcolor=" . formatString($data['gfbkgcolor']);
    	$facility .= "gftxtcolor=" . formatString($data['gftxtcolor']);
    	$facility .= insertNewLine(1);
    	$facility .= "gcbkgcolor=" . formatString($data['gcbkgcolor']);
    	$facility .= "gctxtcolor=" . formatString($data['gctxtcolor']);
    	$facility .= "/>";
    
    
    
    	$myfile = fopen('application/packages/myfile.txt', 'w+');
    	fwrite($myfile, $facility);
    	fclose($myfile);
    	// echo $facility;
    });

    【讨论】:

    • 另一种方式!但是您不需要连接 XML 内容,因为 PHP 带有 DOM class methodscreateElement()setAttribute()appendChild()...
    猜你喜欢
    • 2015-06-30
    • 2016-08-26
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    相关资源
    最近更新 更多