从 XML 中的嵌套属性节点中选择和读取值
Selecting and reading values from nested attribute nodes in XML
我有一个 PHP 脚本,它读取 XML 文件并将其转换为我的 XML 格式。原来的XML是这样的:
<?xml version="1.0" encoding="utf-8"?>
<root>
<products>
<product>
<id>1</id>
<stock>23</stock>
... 6 more nodes....
<pictures>
<pic1>linktopic1.jpg</pic1>
<pic2>linktopic2.jpg</pic2>
</pictures>
<tax_percent>...</tax_percent>
<price_dc>....</price_dc>
...... some more nodes....
<attributes>
<attribute name="Sample attribute" value="Sample value" />
<attribute name="Sample attribute 2" value="Sample value 2"/>
.... 10+ attributes for each product....
</attributes>
</product>
</products>
</root>
我正在使用 XMLwriter 读取 XML 并写入新的 XML。位于不同节点中的所有图片和属性必须放在一个字符串中。我设法为图片做了这个,但它不适用于属性。
foreach($xml->children() as $products) {
foreach($products->children() as $product) {
$newXML->startElement("product");
$newXML->writeElement("ID", $product->id);
$newXML->writeElement("Stock", $product->stock);
$pic=""; // string resets for each product node
$atr=""; // Attribute string
foreach($product->pictures as $child) { // pictures
if ($child->pic1!="") { $pic=$pic.$child->pic1.","; } // If the picture subnode exists it appends the image to previous ones
if ($child->pic2!="") { $pic=$pic.$child->pic2.","; }
if ($child->pic3!="") { $pic=$pic.$child->pic3.","; }
}
foreach($product->attributes as $child) { //attributes
if ($child->attribute['name']=="Sample attribute") { $atr=$atr.$child->attribute['name'].':'.$child->attribute['value'].','; }
if ($child->attribute['name']=="Sample attribute 2") { $atr=$atr.$child->attribute['name'].':'.$child->attribute['value'].','; }
}
..... some more spaghetti code....
正如我所说,图片代码可以正常工作,但由于某些原因,属性代码仅将产品的第一个属性写入字符串并跳过所有其他属性。
有人知道为什么 foreach 循环会跳过所有其他属性节点吗?对我来说,它看起来有点问题,因为属性节点具有相同的节点名称,而图片具有动态名称,idk..
考虑更深入地迭代 <attribute>
标签:
foreach($product->attributes->attribute as $child) { //attributes
if ($child['name']=="Sample attribute") { $atr=$atr.$child['name'].': '.$child['value'].','; }
if ($child['name']=="Sample attribute 2") { $atr=$atr.$child['name'].': '.$child['value'].','; }
}
事实上,您甚至不需要 if
语句:
foreach($product->attributes->attribute as $child) { //attributes
$atr=$atr.$child['name'].': '.$child['value'].',';
}
或者,由于您需要将源 XML 转换为最终的 XML,请考虑 XSLT,专门设计用于转换 XML 文档的专用语言. PHP 在 .ini 文件中启用扩展名(extension=php_xsl.so 或 extension=php_xsl.dll)保持XSLT 1.0 处理器。下面的 XSLT 连接图片和属性的子值(可扩展到 10+ 个节点):
XSLT (另存为 .xsl 文件以在下面 PHP 中加载)
<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="*"/>
<xsl:template match="products">
<xsl:copy>
<xsl:apply-templates select="product"/>
</xsl:copy>
</xsl:template>
<xsl:template match="product">
<xsl:copy>
<xsl:copy-of select="id|stock"/>
<pictures>
<xsl:for-each select="pictures">
<xsl:value-of select="concat(pic1, ', ', pic2)" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</pictures>
<attributes>
<xsl:for-each select="attributes/attribute">
<xsl:value-of select="concat(@name, ': ', @value)" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</attributes>
</xsl:copy>
</xsl:template>
</xsl:transform>
PHP (没有for循环,没有if语句,没有局部变量,没有意大利面条代码)
// LOAD XML AND XSL SOURCES
$xml = simplexml_load_file('Input.xml');
$xsl = simplexml_load_file('XSLTScript.xsl');
// CONFIGURE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($xml);
echo $newXML;
// <?xml version="1.0" encoding="UTF-8"?>
// <products>
// <product>
// <id>1</id>
// <stock>23</stock>
// <pictures>linktopic1.jpg, linktopic2.jpg</pictures>
// <attributes>Sample attribute: Sample value, Sample attribute 2: Sample value 2</attributes>
// </product>
// </products>
我有一个 PHP 脚本,它读取 XML 文件并将其转换为我的 XML 格式。原来的XML是这样的:
<?xml version="1.0" encoding="utf-8"?>
<root>
<products>
<product>
<id>1</id>
<stock>23</stock>
... 6 more nodes....
<pictures>
<pic1>linktopic1.jpg</pic1>
<pic2>linktopic2.jpg</pic2>
</pictures>
<tax_percent>...</tax_percent>
<price_dc>....</price_dc>
...... some more nodes....
<attributes>
<attribute name="Sample attribute" value="Sample value" />
<attribute name="Sample attribute 2" value="Sample value 2"/>
.... 10+ attributes for each product....
</attributes>
</product>
</products>
</root>
我正在使用 XMLwriter 读取 XML 并写入新的 XML。位于不同节点中的所有图片和属性必须放在一个字符串中。我设法为图片做了这个,但它不适用于属性。
foreach($xml->children() as $products) {
foreach($products->children() as $product) {
$newXML->startElement("product");
$newXML->writeElement("ID", $product->id);
$newXML->writeElement("Stock", $product->stock);
$pic=""; // string resets for each product node
$atr=""; // Attribute string
foreach($product->pictures as $child) { // pictures
if ($child->pic1!="") { $pic=$pic.$child->pic1.","; } // If the picture subnode exists it appends the image to previous ones
if ($child->pic2!="") { $pic=$pic.$child->pic2.","; }
if ($child->pic3!="") { $pic=$pic.$child->pic3.","; }
}
foreach($product->attributes as $child) { //attributes
if ($child->attribute['name']=="Sample attribute") { $atr=$atr.$child->attribute['name'].':'.$child->attribute['value'].','; }
if ($child->attribute['name']=="Sample attribute 2") { $atr=$atr.$child->attribute['name'].':'.$child->attribute['value'].','; }
}
..... some more spaghetti code....
正如我所说,图片代码可以正常工作,但由于某些原因,属性代码仅将产品的第一个属性写入字符串并跳过所有其他属性。
有人知道为什么 foreach 循环会跳过所有其他属性节点吗?对我来说,它看起来有点问题,因为属性节点具有相同的节点名称,而图片具有动态名称,idk..
考虑更深入地迭代 <attribute>
标签:
foreach($product->attributes->attribute as $child) { //attributes
if ($child['name']=="Sample attribute") { $atr=$atr.$child['name'].': '.$child['value'].','; }
if ($child['name']=="Sample attribute 2") { $atr=$atr.$child['name'].': '.$child['value'].','; }
}
事实上,您甚至不需要 if
语句:
foreach($product->attributes->attribute as $child) { //attributes
$atr=$atr.$child['name'].': '.$child['value'].',';
}
或者,由于您需要将源 XML 转换为最终的 XML,请考虑 XSLT,专门设计用于转换 XML 文档的专用语言. PHP 在 .ini 文件中启用扩展名(extension=php_xsl.so 或 extension=php_xsl.dll)保持XSLT 1.0 处理器。下面的 XSLT 连接图片和属性的子值(可扩展到 10+ 个节点):
XSLT (另存为 .xsl 文件以在下面 PHP 中加载)
<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="*"/>
<xsl:template match="products">
<xsl:copy>
<xsl:apply-templates select="product"/>
</xsl:copy>
</xsl:template>
<xsl:template match="product">
<xsl:copy>
<xsl:copy-of select="id|stock"/>
<pictures>
<xsl:for-each select="pictures">
<xsl:value-of select="concat(pic1, ', ', pic2)" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</pictures>
<attributes>
<xsl:for-each select="attributes/attribute">
<xsl:value-of select="concat(@name, ': ', @value)" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</attributes>
</xsl:copy>
</xsl:template>
</xsl:transform>
PHP (没有for循环,没有if语句,没有局部变量,没有意大利面条代码)
// LOAD XML AND XSL SOURCES
$xml = simplexml_load_file('Input.xml');
$xsl = simplexml_load_file('XSLTScript.xsl');
// CONFIGURE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($xml);
echo $newXML;
// <?xml version="1.0" encoding="UTF-8"?>
// <products>
// <product>
// <id>1</id>
// <stock>23</stock>
// <pictures>linktopic1.jpg, linktopic2.jpg</pictures>
// <attributes>Sample attribute: Sample value, Sample attribute 2: Sample value 2</attributes>
// </product>
// </products>