php - 使用 PHP 和 XPATH 呈现嵌入在 XML 节点中的 XML 节点

标签 php xml xpath namespaces

我正在尝试使用 PHP 解析带有命名空间的 XML 文档以输出 HTML,并保留其原始结构。
我在下面的代码中使用了 XPATH 和 foreach 循环来呈现标题、段落和列表,但这不尊重文档的原始结构。我也不清楚如何呈现诸如嵌入在内容中的 URL 之类的内容,该内容也包含在 XML 标记中。
XML 示例:

<a:section>
<c:ref value="1">1</c:ref>
<c:title>Title of content</c:title>

<f:subsection>
<c:ref value="1.1">1.1</c:ref>
<c:title>Subsection title</c:title>

<b:content>Make sure you check out this link: <c:url address="www.google.com" type="https">google.com</c:url> and then review the list below:</b:content>
    <c:list type="bullet">
        <c:listitem>
            <b:content>bullet item 1</b:content>
        </c:listitem>
        <c:listitem>
            <b:content>bullet item 2</b:content>
        </c:listitem>
        <c:listitem>
            <b:content>bullet item 3</b:content>
        </c:listitem>
    </c:list>
<b:content>More content here in text form</b:content>

</f:subsection>

</a:section>
PHP 示例:
$xml = file_get_contents('content.xml');
$sxml = new SimpleXmlElement($xml);
$section = $sxml->xpath('//a:section');

foreach ($section as $s) {
    $sectionnumber = $s->xpath('c:ref');
    $title = $s->xpath('c:title');
    foreach ($title as $t) {
        echo '<h2>'.$sectionnumber[0].' '.$t.'</h2>';
    }
}

$subsection = $s->xpath('f:subsection');
    foreach ($subsection as $ss) {
      $subheadingnumber = $ss->xpath('c:ref');
      $subheading = $ss->xpath('c:title');
      foreach ($subheading as $sh) {
          echo '<h3>'.$subheadingnumber[0].' '.$sh.'</h3>';
      }
      $paragraphs = $ss->xpath('b:content');
      foreach ($paragraphs as $p){
        echo '<p>'.$p.'</p>';
      }
      $lists = $ss->xpath('c:list');
      foreach ($lists as $l){
        $listitem = $l->xpath('c:listitem');
        foreach ($listitem as $item){
          $listcontent = $item->xpath('b:content');
          foreach ($listcontent as $a){
            echo '<li>'.$a.'</li>';
          }
        }
      }
    }

最佳答案

您缺少带有命名空间定义的文档元素。他们是
important 并且您不应该依赖前缀(它们可以更改并且对于元素是可选的)。
对于这个答案,我添加了一个带有虚拟命名空间的文档元素。

<?xml version="1.0" encoding="utf-8" ?>
<a:content
  xmlns:a="urn:a"
  xmlns:b="urn:b"
  xmlns:c="urn:c"
  xmlns:f="urn:f">
  <a:section>
    ...
XSLT 正是为此目的而设计的模板语言。它允许您定义节点的匹配项并转换它们:
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:a="urn:a"
  xmlns:b="urn:b"
  xmlns:c="urn:c"
  xmlns:f="urn:f"
  exclude-result-prefixes="a b c f">

  <xsl:output method="html"/>

  <xsl:template match="/*">
    <div>
      <xsl:for-each select="a:section">
        <h2><xsl:value-of select="c:title"/></h2>
        <xsl:for-each select="f:subsection">
          <h3><xsl:value-of select="c:title"/></h3>
          <div><xsl:apply-templates select="b:content|c:list"/></div>
        </xsl:for-each>
      </xsl:for-each>
    </div>
  </xsl:template>

  <xsl:template match="b:content">
    <p><xsl:apply-templates/></p>
  </xsl:template>

  <xsl:template match="c:list">
    <ul>
      <xsl:for-each select="c:listitem">
        <li><xsl:apply-templates/></li>
      </xsl:for-each>
    </ul>
  </xsl:template>

  <xsl:template match="c:url">
    <a href="{@type}://{@address}"><xsl:apply-templates/></a>
  </xsl:template>

</xsl:stylesheet>
注意匹配 XML 文档中的命名空间。
PHP 将加载 XML 和模板并对其进行处理:
// load the content
$content = new DOMDocument();
$content->load(__DIR__.'/content.xml');
// load the template
$template = new DOMDocument();
$template->load(__DIR__.'/transform.xsl');
// bootstrap XSLT
$processor = new XSLTProcessor();
$processor->importStylesheet($template);
// transform and output
echo $processor->transformToXml($content);
输出:
<div>
  <h2>Title of content</h2>
  <h3>Subsection title</h3>
  <div>
    <p>Make sure you check out this link: <a href="https://www.google.com">google.com</a> and then review the list below:</p>
    <ul>
      <li><p>bullet item 1</p></li>
      <li><p>bullet item 2</p></li>
      <li><p>bullet item 3</p></li>
    </ul>
    <p>More content here in text form</p>
  </div>
</div>

关于php - 使用 PHP 和 XPATH 呈现嵌入在 XML 节点中的 XML 节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69851362/

相关文章:

c# - 如何使用 Selenium for C# 通过 XPath 查找文本?

php - 如何在php中获取图像类型

php - 多次mysql查询导致返回null

python - 将 .CSV 文件转换为 .XML

xml - 如何使用 vbscript 删除 XML 文件中的节点?

python - Scrapy 响应在元素属性中有反斜杠

javascript - 如何在未选中复选框时删除值?

php - 使用php将XML数据插入mysql

Java:将 bytearray 转换为字符串和 xml

xml - 列出或计算从当前节点到每个叶节点的具有某些属性的路径