我正在使用PHP5,我需要以下列形式转换XML:
<item>
<string isNewLine="1" lineNumber="32">some text in new line</string>
<string>, more text</string>
<item>
<string isNewLine="1" lineNumber="33">some text in new line</string>
<string isNewLine="1" lineNumber="34">some text</string>
<string> in the same line</string>
<string isNewLine="1" lineNumber="35">some text in new line</string>
</item>
</item>
这样的事情:
<item>
<line lineNumber="32">some text in new line, more text</string>
<item>
<line lineNumber="33">some text in new line</string>
<line lineNumber="34">some text in the same line</string>
<line lineNumber="35">some text in new line</string>
</item>
</item>
正如您所看到的,它已加入多个“字符串”节点中包含的文本。 另请注意,“字符串”节点可以嵌套在任何级别的其他节点中。
将源xml转换为目标xml有哪些可能的解决方案?
谢谢,
答案 0 :(得分:2)
此样式表生成您要查找的输出:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" />
<!--Identity template simply copies content forward by default -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="string[@isNewLine and @lineNumber]">
<line>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="text()" />
<!-- Include the text() from the string elements that come after this element,
do not have @isNewLine or @lineNumber,
and are only following this particular element -->
<xsl:apply-templates select="following-sibling::string[not(@isNewLine and @lineNumber) and generate-id(preceding-sibling::string[1]) = generate-id(current())]/text()" />
</line>
</xsl:template>
<!--Suppress the string elements that do not contain isNewLine or lineNumber attributes in normal processing-->
<xsl:template match="string[not(@isNewLine and @lineNumber)]" />
<!--Empty template to prevent attribute from being copied to output-->
<xsl:template match="@isNewLine" />
</xsl:stylesheet>
答案 1 :(得分:2)
这是一个有效且正确的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="knextStrings"
match="string[not(@isNewLine)]"
use="generate-id(preceding-sibling::string
[@isNewLine][1]
)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="string[@isNewLine]">
<line>
<xsl:copy-of select="@*[not(name()='isNewLine')]"/>
<xsl:copy-of select="text()
|
key('knextStrings',
generate-id()
)
/text()"/>
</line>
</xsl:template>
<xsl:template match="string[not(@isNewLine)]"/>
</xsl:stylesheet>
将此转换应用于最初提供的XML文档:
<item>
<string isNewLine="1" lineNumber="32">some text in new line</string>
<string>, more text</string>
<item>
<string isNewLine="1" lineNumber="33">some text in new line</string>
<string isNewLine="1" lineNumber="34">some text</string>
<string> in the same line</string>
<string isNewLine="1" lineNumber="35">some text in new line</string>
</item>
</item>
产生了想要的正确结果:
<item>
<line lineNumber="32">some text in new line, more text</line>
<item>
<line lineNumber="33">some text in new line</line>
<line lineNumber="34">some text in the same line</line>
<line lineNumber="35">some text in new line</line>
</item>
</item>
答案 2 :(得分:0)
您应该为此查看XML Parser。您可以使用基于SAX或基于DOM的解析器。
SAX效率更高,但DOM可以更好地满足您的需求,因为它更容易使用。
答案 3 :(得分:0)
使用XSL转换。
<?php
$xml = new DOMDocument;
$xml->load('data.xml');
$xsl = new DOMDocument;
$xsl->load('trans.xsl');
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($xml);
?>
使用Dimitri对trans.xsl
的回答。