如何在站点地图中包含类似 ™ 的内容
How to Include Something Like ™ in a Sitemap
我正在尝试使用 php 生成站点地图,但出现错误,因为我的某些产品名称包含“&trade”。
我知道 & 需要转义为 &,但我不确定如何处理 &trade。这是一个很难搜索的问题,我敢肯定它会出现在某人身上,但我找不到相关的东西。
// Remove Whitespace from Links
function url_safe ($data) {
$data = preg_replace('/\s/', '-', htmlentities($data));
return $data;
}
//URLs for Products
$query = "SELECT product_id, product_name FROM product WHERE active = 'Y'";
$result = mysqli_query($dbc, $query) or die(mysqli_error($dbc) . '<br />Query: ' . $query);
while($row = mysqli_fetch_array($result)) {
$data .= "\t<url>\n";
$data .= "\t\t<loc>https://www.example.com/product.php?pid=$row[0]&name=" . url_safe($row[1]) . "</loc>\n";
$data .= "\t\t<changefreq>monthly</changefreq>\n";
$data .= "\t\t<priority>1.0</priority>\n";
$data .= "\t</url>\n";
$i++;
}
对于标题中包含 &trade 的任何产品,这是我遇到的错误。
XML 解析错误:未定义实体
这是导致错误的生成输出示例。
<url>
<loc>https://www.example.com/product.php?pid=2738&name=My-Product™-Has-A-Trademark</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
您正在寻找 urlencode
。
This function is convenient when encoding a string to be used in a query part of a URL, as a convenient way to pass variables to the next page.
保留大部分原始代码,结果应如下所示:
// Remove Whitespace from Links
function url_safe ($data) {
$data = preg_replace('/\s/', '-', htmlentities($data));
// Adding url encoding
$data = urlencode($data);
return $data;
}
//URLs for Products
$query = "SELECT product_id, product_name FROM product WHERE active = 'Y'";
$result = mysqli_query($dbc, $query) or die(mysqli_error($dbc) . '<br />Query: ' . $query);
while($row = mysqli_fetch_array($result)) {
$data .= "\t<url>\n";
$data .= "\t\t<loc>https://www.example.com/product.php?pid=$row[0]&name=" . url_safe($row[1]) . "</loc>\n";
$data .= "\t\t<changefreq>monthly</changefreq>\n";
$data .= "\t\t<priority>1.0</priority>\n";
$data .= "\t</url>\n";
$i++;
}
有关更多信息,请参阅 https://www.php.net/manual/en/function.urlencode.php。
XML 不支持像 ™
这样的命名实体,只有 (X)HTML 有。 (或定义它们的其他基于 XML 的格式。)
这里有两种特殊字符的解决方法。您可以只将 XML 定义为 UTF-8 并直接使用该字符,也可以使用数字实体。
这是 DOM 的一个例子:
$document = new DOMDocument('1.0', 'UTF-8');
$document
->appendChild($document->createElement('foo'))
->textContent = '™';
echo $document->saveXML();
$document = new DOMDocument('1.0', 'ASCII');
$document
->appendChild($document->createElement('foo'))
->textContent = '™';
echo $document->saveXML();
输出:
<?xml version="1.0" encoding="UTF-8"?>
<foo>™</foo>
<?xml version="1.0" encoding="ASCII"?>
<foo>™</foo>
您可以看到,在 UTF-8 编码的 XML 中,它使用字符,而在 ASCII 编码中,它将它编码为数字实体。
您的示例有点不同,因为您将变量放入 URL 的查询字符串中。所以你必须首先为它们编码,然后为 XML 文本节点编码 URL 。为 URL 编码变量的函数是 urlencode()
和 rawurlencode()
。我喜欢使用 sprintf()
来提高可读性。下面是构建 URLs 的示例:
$data = [
[1, 'foo'],
[2, 'foo ™'],
[3, 'foo & bar'],
];
foreach ($data as $item) {
$url = sprintf(
'https://www.example.com/product.php?pid=%s&name=%s',
urlencode($item[0]),
urlencode($item[1])
);
echo $url, "\n";
}
输出:
https://www.example.com/product.php?pid=1&name=foo
https://www.example.com/product.php?pid=2&name=foo+%E2%84%A2
https://www.example.com/product.php?pid=3&name=foo+%26+bar
您正在将 XML 创建为 TEXT,但是 PHP 恰好为此作业实施了 XMLWriter。使用 API 将处理 XML 中具有特殊含义的字符 - 就像用于分隔 URL 参数的 &
一样。
$data = [
[1, 'foo'],
[2, 'foo ™'],
[3, 'foo & bar'],
];
$writer = new XMLWriter();
$writer->openURI('php://stdout');
$writer->setIndent(1);
$writer->setIndentString("\t");
$writer->startDocument();
$writer->startElementNS(NULL, 'urlset', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($data as $item) {
$writer->startElement('url');
$writer->writeElement(
'loc',
sprintf(
'https://www.example.com/product.php?pid=%s&name=%s',
urlencode($item[0]),
urlencode($item[1])
)
);
$writer->writeElement('changefreq', 'monthly');
$writer->writeElement('priority', '1.0');
$writer->endElement();
}
$writer->endElement();
$writer->endDocument();
输出:
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/product.php?pid=1&name=foo</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.example.com/product.php?pid=2&name=foo+%E2%84%A2</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.example.com/product.php?pid=3&name=foo+%26+bar</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
</urlset>
我正在尝试使用 php 生成站点地图,但出现错误,因为我的某些产品名称包含“&trade”。
我知道 & 需要转义为 &,但我不确定如何处理 &trade。这是一个很难搜索的问题,我敢肯定它会出现在某人身上,但我找不到相关的东西。
// Remove Whitespace from Links
function url_safe ($data) {
$data = preg_replace('/\s/', '-', htmlentities($data));
return $data;
}
//URLs for Products
$query = "SELECT product_id, product_name FROM product WHERE active = 'Y'";
$result = mysqli_query($dbc, $query) or die(mysqli_error($dbc) . '<br />Query: ' . $query);
while($row = mysqli_fetch_array($result)) {
$data .= "\t<url>\n";
$data .= "\t\t<loc>https://www.example.com/product.php?pid=$row[0]&name=" . url_safe($row[1]) . "</loc>\n";
$data .= "\t\t<changefreq>monthly</changefreq>\n";
$data .= "\t\t<priority>1.0</priority>\n";
$data .= "\t</url>\n";
$i++;
}
对于标题中包含 &trade 的任何产品,这是我遇到的错误。
XML 解析错误:未定义实体
这是导致错误的生成输出示例。
<url>
<loc>https://www.example.com/product.php?pid=2738&name=My-Product™-Has-A-Trademark</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
您正在寻找 urlencode
。
This function is convenient when encoding a string to be used in a query part of a URL, as a convenient way to pass variables to the next page.
保留大部分原始代码,结果应如下所示:
// Remove Whitespace from Links
function url_safe ($data) {
$data = preg_replace('/\s/', '-', htmlentities($data));
// Adding url encoding
$data = urlencode($data);
return $data;
}
//URLs for Products
$query = "SELECT product_id, product_name FROM product WHERE active = 'Y'";
$result = mysqli_query($dbc, $query) or die(mysqli_error($dbc) . '<br />Query: ' . $query);
while($row = mysqli_fetch_array($result)) {
$data .= "\t<url>\n";
$data .= "\t\t<loc>https://www.example.com/product.php?pid=$row[0]&name=" . url_safe($row[1]) . "</loc>\n";
$data .= "\t\t<changefreq>monthly</changefreq>\n";
$data .= "\t\t<priority>1.0</priority>\n";
$data .= "\t</url>\n";
$i++;
}
有关更多信息,请参阅 https://www.php.net/manual/en/function.urlencode.php。
XML 不支持像 ™
这样的命名实体,只有 (X)HTML 有。 (或定义它们的其他基于 XML 的格式。)
这里有两种特殊字符的解决方法。您可以只将 XML 定义为 UTF-8 并直接使用该字符,也可以使用数字实体。
这是 DOM 的一个例子:
$document = new DOMDocument('1.0', 'UTF-8');
$document
->appendChild($document->createElement('foo'))
->textContent = '™';
echo $document->saveXML();
$document = new DOMDocument('1.0', 'ASCII');
$document
->appendChild($document->createElement('foo'))
->textContent = '™';
echo $document->saveXML();
输出:
<?xml version="1.0" encoding="UTF-8"?>
<foo>™</foo>
<?xml version="1.0" encoding="ASCII"?>
<foo>™</foo>
您可以看到,在 UTF-8 编码的 XML 中,它使用字符,而在 ASCII 编码中,它将它编码为数字实体。
您的示例有点不同,因为您将变量放入 URL 的查询字符串中。所以你必须首先为它们编码,然后为 XML 文本节点编码 URL 。为 URL 编码变量的函数是 urlencode()
和 rawurlencode()
。我喜欢使用 sprintf()
来提高可读性。下面是构建 URLs 的示例:
$data = [
[1, 'foo'],
[2, 'foo ™'],
[3, 'foo & bar'],
];
foreach ($data as $item) {
$url = sprintf(
'https://www.example.com/product.php?pid=%s&name=%s',
urlencode($item[0]),
urlencode($item[1])
);
echo $url, "\n";
}
输出:
https://www.example.com/product.php?pid=1&name=foo
https://www.example.com/product.php?pid=2&name=foo+%E2%84%A2
https://www.example.com/product.php?pid=3&name=foo+%26+bar
您正在将 XML 创建为 TEXT,但是 PHP 恰好为此作业实施了 XMLWriter。使用 API 将处理 XML 中具有特殊含义的字符 - 就像用于分隔 URL 参数的 &
一样。
$data = [
[1, 'foo'],
[2, 'foo ™'],
[3, 'foo & bar'],
];
$writer = new XMLWriter();
$writer->openURI('php://stdout');
$writer->setIndent(1);
$writer->setIndentString("\t");
$writer->startDocument();
$writer->startElementNS(NULL, 'urlset', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($data as $item) {
$writer->startElement('url');
$writer->writeElement(
'loc',
sprintf(
'https://www.example.com/product.php?pid=%s&name=%s',
urlencode($item[0]),
urlencode($item[1])
)
);
$writer->writeElement('changefreq', 'monthly');
$writer->writeElement('priority', '1.0');
$writer->endElement();
}
$writer->endElement();
$writer->endDocument();
输出:
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.example.com/product.php?pid=1&name=foo</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.example.com/product.php?pid=2&name=foo+%E2%84%A2</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.example.com/product.php?pid=3&name=foo+%26+bar</loc>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
</urlset>