You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@any23.apache.org by ha...@apache.org on 2018/10/30 03:29:20 UTC
[1/3] any23 git commit: ANY23-240 insert newlines where advisable in
microdata
Repository: any23
Updated Branches:
refs/heads/master f87ac66bc -> 2175c2d37
ANY23-240 insert newlines where advisable in microdata
Project: http://git-wip-us.apache.org/repos/asf/any23/repo
Commit: http://git-wip-us.apache.org/repos/asf/any23/commit/837d1935
Tree: http://git-wip-us.apache.org/repos/asf/any23/tree/837d1935
Diff: http://git-wip-us.apache.org/repos/asf/any23/diff/837d1935
Branch: refs/heads/master
Commit: 837d1935baa8bbc487bc806c063627cd04f4c134
Parents: f87ac66
Author: Hans <fi...@gmail.com>
Authored: Mon Oct 29 20:22:02 2018 -0500
Committer: Hans <fi...@gmail.com>
Committed: Mon Oct 29 20:22:02 2018 -0500
----------------------------------------------------------------------
.../extractor/microdata/MicrodataParser.java | 55 +++++++++++++++++++-
.../schemaorg-example-2-expected.nquads | 2 +-
2 files changed, 55 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/any23/blob/837d1935/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
index 8964b32..013a318 100644
--- a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
+++ b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
@@ -23,10 +23,12 @@ import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.vocabulary.XMLSchema;
+import org.jsoup.parser.Tag;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
@@ -39,6 +41,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -417,12 +420,62 @@ public class MicrodataParser {
}
String lang = getLanguage(node);
- Literal l = lang == null ? RDFUtils.literal(node.getTextContent()) : RDFUtils.literal(node.getTextContent(), lang);
+ StringBuilder content = new StringBuilder();
+ appendFormatted(node, content, false);
+ Literal l = RDFUtils.literal(content.toString(), lang);
final ItemPropValue newItemPropValue = new ItemPropValue(l);
itemPropValues.put(node, newItemPropValue);
return newItemPropValue;
}
+ private static boolean shouldSeparateWithNewline(CharSequence s0, CharSequence s1) {
+ for (int i = 0, len = s1.length(); i < len; i++) {
+ char ch = s1.charAt(i);
+ if (ch == '\n' || ch == '\r') {
+ return false;
+ }
+ if (!Character.isWhitespace(ch)) {
+ break;
+ }
+ }
+ for (int i = s0.length() - 1; i >= 0; i--) {
+ char ch = s0.charAt(i);
+ if (ch == '\n' || ch == '\r') {
+ return false;
+ }
+ if (!Character.isWhitespace(ch)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean appendFormatted(Node node, StringBuilder sb, boolean needsNewline) {
+ switch (node.getNodeType()) {
+ case Node.TEXT_NODE:
+ String text = node.getTextContent();
+ if (text.isEmpty()) {
+ return needsNewline;
+ }
+ if (needsNewline && shouldSeparateWithNewline(sb, text)) {
+ sb.append('\n');
+ }
+ sb.append(text);
+ return false;
+ case Node.ELEMENT_NODE:
+ final String nodeName = node.getNodeName().toLowerCase(Locale.ENGLISH);
+ final boolean thisNeedsNewline = "br".equals(nodeName) || Tag.valueOf(nodeName).isBlock();
+ final NodeList children = node.getChildNodes();
+ boolean prevChildNeedsNewline = needsNewline || thisNeedsNewline;
+ for (int i = 0, len = children.getLength(); i < len; i++) {
+ prevChildNeedsNewline = appendFormatted(children.item(i), sb, prevChildNeedsNewline);
+ }
+ return prevChildNeedsNewline || thisNeedsNewline;
+ default:
+ return needsNewline;
+ }
+ }
+
private static String readContentAttribute(Node node, String attrName) {
NamedNodeMap attributes = node.getAttributes();
if (attributes != null) {
http://git-wip-us.apache.org/repos/asf/any23/blob/837d1935/test-resources/src/test/resources/microdata/schemaorg-example-2-expected.nquads
----------------------------------------------------------------------
diff --git a/test-resources/src/test/resources/microdata/schemaorg-example-2-expected.nquads b/test-resources/src/test/resources/microdata/schemaorg-example-2-expected.nquads
index cc86cf9..2258212 100644
--- a/test-resources/src/test/resources/microdata/schemaorg-example-2-expected.nquads
+++ b/test-resources/src/test/resources/microdata/schemaorg-example-2-expected.nquads
@@ -17,7 +17,7 @@
_:node8b30931f1dde708283dc52546c5572a6 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Product> <http://bob.example.com/> .
_:node8b30931f1dde708283dc52546c5572a6 <http://schema.org/price> "$55,000.00" <http://bob.example.com/> .
-_:node8b30931f1dde708283dc52546c5572a6 <http://schema.org/description> "2010 Dodge Challenger SRT8 Limited EditionBright Silver Metallic with Dark Slate Gray Leather Interior6.1 Liter (370 CI) V8 SRT HEMI Engine6 Speed Manual Transmission with 3:92 Rear Axle Ratio (DEC, Track Pak)" <http://bob.example.com/> .
+_:node8b30931f1dde708283dc52546c5572a6 <http://schema.org/description> "2010 Dodge Challenger SRT8 Limited Edition\nBright Silver Metallic with Dark Slate Gray Leather Interior\n6.1 Liter (370 CI) V8 SRT HEMI Engine\n6 Speed Manual Transmission with 3:92 Rear Axle Ratio (DEC, Track Pak)" <http://bob.example.com/> .
_:node8b30931f1dde708283dc52546c5572a6 <http://schema.org/name> "2010 Dodge Challenger SRT8" <http://bob.example.com/> .
_:node8b30931f1dde708283dc52546c5572a6 <http://schema.org/image> <http://bob.example.com/microdata/images/2010-dodge-challenger-srt8.jpg> <http://bob.example.com/> .
_:node8b30931f1dde708283dc52546c5572a6 <http://schema.org/url> <http://vheminc.com/> <http://bob.example.com/> .
[2/3] any23 git commit: check for itemscope before content,
as per microdata spec
Posted by ha...@apache.org.
check for itemscope before content, as per microdata spec
Project: http://git-wip-us.apache.org/repos/asf/any23/repo
Commit: http://git-wip-us.apache.org/repos/asf/any23/commit/4f280409
Tree: http://git-wip-us.apache.org/repos/asf/any23/tree/4f280409
Diff: http://git-wip-us.apache.org/repos/asf/any23/diff/4f280409
Branch: refs/heads/master
Commit: 4f2804094751e1522428305938e3a4c4b13d2aa4
Parents: 837d193
Author: Hans <fi...@gmail.com>
Authored: Mon Oct 29 21:39:05 2018 -0500
Committer: Hans <fi...@gmail.com>
Committed: Mon Oct 29 21:39:05 2018 -0500
----------------------------------------------------------------------
.../extractor/microdata/MicrodataParser.java | 69 +++++++++++---------
1 file changed, 38 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/any23/blob/4f280409/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
index 013a318..c086d3f 100644
--- a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
+++ b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
@@ -353,14 +353,18 @@ public class MicrodataParser {
*/
public ItemPropValue getPropertyValue(Node node) throws MicrodataParserException {
final ItemPropValue itemPropValue = itemPropValues.get(node);
- if(itemPropValue != null)
+ if (itemPropValue != null)
return itemPropValue;
+ if (isItemScope(node)) {
+ return new ItemPropValue( getItemScope(node), ItemPropValue.Type.Nested);
+ }
+
final String nodeName = node.getNodeName().toLowerCase();
//see http://w3c.github.io/microdata-rdf/#dfn-property-values
if ("data".equals(nodeName) || "meter".equals(nodeName)) {
- String value = StringUtils.stripToEmpty(readContentAttribute(node, "value"));
+ String value = value(node, "value");
Literal l;
if (XMLDatatypeUtil.isValidInteger(value)) {
l = RDFUtils.literal(value, XMLSchema.INTEGER);
@@ -371,8 +375,8 @@ public class MicrodataParser {
}
return new ItemPropValue(l);
}
- if( "time".equals(nodeName) ) {
- String dateTimeStr = StringUtils.stripToEmpty(readContentAttribute(node, "datetime"));
+ if ("time".equals(nodeName)) {
+ String dateTimeStr = value(node, "datetime");
Literal l;
if (XMLDatatypeUtil.isValidDate(dateTimeStr)) {
l = RDFUtils.literal(dateTimeStr, XMLSchema.DATE);
@@ -387,47 +391,39 @@ public class MicrodataParser {
} else if (XMLDatatypeUtil.isValidDuration(dateTimeStr)) {
l = RDFUtils.literal(dateTimeStr, XMLSchema.DURATION);
} else {
- String lang = getLanguage(node);
- if (lang != null) {
- l = RDFUtils.literal(dateTimeStr, lang);
- } else {
- l = RDFUtils.literal(dateTimeStr);
- }
+ l = RDFUtils.literal(dateTimeStr, getLanguage(node));
}
return new ItemPropValue(l);
}
- if (DomUtils.hasAttribute(node, "content")) {
- String val = DomUtils.readAttribute(node, "content");
- String lang = getLanguage(node);
- Literal l = lang == null ? RDFUtils.literal(val) : RDFUtils.literal(val, lang);
- return new ItemPropValue(l);
- }
-
- if( SRC_TAGS.contains(nodeName) ) {
- return new ItemPropValue( DomUtils.readAttribute(node, "src"), ItemPropValue.Type.Link);
+ if (SRC_TAGS.contains(nodeName)) {
+ return link(node, "src");
}
- if( HREF_TAGS.contains(nodeName) ) {
- return new ItemPropValue( DomUtils.readAttribute(node, "href"), ItemPropValue.Type.Link);
+ if (HREF_TAGS.contains(nodeName)) {
+ return link(node, "href");
}
- if( "object".equals(nodeName) ) {
- return new ItemPropValue( DomUtils.readAttribute(node, "data"), ItemPropValue.Type.Link);
+ if ("object".equals(nodeName)) {
+ return link(node, "data");
}
- if( isItemScope(node) ) {
- return new ItemPropValue( getItemScope(node), ItemPropValue.Type.Nested);
+ String val = DomUtils.readAttribute(node, "content", null);
+ if (val != null) {
+ return new ItemPropValue(RDFUtils.literal(val, getLanguage(node)));
}
- String lang = getLanguage(node);
- StringBuilder content = new StringBuilder();
- appendFormatted(node, content, false);
- Literal l = RDFUtils.literal(content.toString(), lang);
+ Literal l = RDFUtils.literal(textContent(node), getLanguage(node));
final ItemPropValue newItemPropValue = new ItemPropValue(l);
itemPropValues.put(node, newItemPropValue);
return newItemPropValue;
}
+ private static String textContent(Node node) {
+ StringBuilder content = new StringBuilder();
+ appendFormatted(node, content, false);
+ return content.toString();
+ }
+
private static boolean shouldSeparateWithNewline(CharSequence s0, CharSequence s1) {
for (int i = 0, len = s1.length(); i < len; i++) {
char ch = s1.charAt(i);
@@ -476,7 +472,7 @@ public class MicrodataParser {
}
}
- private static String readContentAttribute(Node node, String attrName) {
+ private static String content(Node node, String attrName) {
NamedNodeMap attributes = node.getAttributes();
if (attributes != null) {
Node attr = attributes.getNamedItem("content");
@@ -488,7 +484,18 @@ public class MicrodataParser {
return attr.getNodeValue();
}
}
- return node.getTextContent();
+ return null;
+ }
+
+ private static String value(Node node, String attrName) {
+ String content = content(node, attrName);
+ return StringUtils.stripToEmpty(content != null ? content : node.getTextContent());
+ }
+
+ private static ItemPropValue link(Node node, String attrName) {
+ String content = content(node, attrName);
+ return content == null ? new ItemPropValue(RDFUtils.literal(""))
+ : new ItemPropValue(content, ItemPropValue.Type.Link);
}
//see https://www.w3.org/TR/html52/dom.html#the-lang-and-xmllang-attributes
[3/3] any23 git commit: require strict isomorphism w/online microdata
tests' expected models
Posted by ha...@apache.org.
require strict isomorphism w/online microdata tests' expected models
Project: http://git-wip-us.apache.org/repos/asf/any23/repo
Commit: http://git-wip-us.apache.org/repos/asf/any23/commit/2175c2d3
Tree: http://git-wip-us.apache.org/repos/asf/any23/tree/2175c2d3
Diff: http://git-wip-us.apache.org/repos/asf/any23/diff/2175c2d3
Branch: refs/heads/master
Commit: 2175c2d376712e2bb7a18c2c17f6527a46aa35ae
Parents: 4f28040
Author: Hans <fi...@gmail.com>
Authored: Mon Oct 29 22:28:45 2018 -0500
Committer: Hans <fi...@gmail.com>
Committed: Mon Oct 29 22:28:45 2018 -0500
----------------------------------------------------------------------
.../extractor/microdata/MicrodataExtractor.java | 2 +-
.../extractor/microdata/MicrodataParser.java | 73 ++++++++------------
.../microdata/MicrodataExtractorTest.java | 4 +-
....2.1-non-normative-example-2-expected.nquads | 2 -
4 files changed, 30 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/any23/blob/2175c2d3/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataExtractor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataExtractor.java b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataExtractor.java
index cac6689..50f880f 100644
--- a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataExtractor.java
+++ b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataExtractor.java
@@ -49,7 +49,7 @@ import java.util.Optional;
*/
public class MicrodataExtractor implements Extractor.TagSoupDOMExtractor {
- private static final IRI MICRODATA_ITEM
+ static final IRI MICRODATA_ITEM
= RDFUtils.iri("http://www.w3.org/1999/xhtml/microdata#item");
private static final ParsedIRI EMPTY_FRAG = ParsedIRI.create("#");
http://git-wip-us.apache.org/repos/asf/any23/blob/2175c2d3/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
index c086d3f..8c3c641 100644
--- a/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
+++ b/core/src/main/java/org/apache/any23/extractor/microdata/MicrodataParser.java
@@ -300,32 +300,6 @@ public class MicrodataParser {
ps.append("}");
}
- /**
- * Returns only nodes that are <b>not</b> nested one each other.
- *
- * @param candidates list of candidate nodes.
- * @return list of unnested nodes.
- */
- @SuppressWarnings("unused")
- private static List<Node> getUnnestedNodes(List<Node> candidates) {
- final List<Node> unnesteds = new ArrayList<>();
- for(int i = 0; i < candidates.size(); i++) {
- boolean skip = false;
- for(int j = 0; j < candidates.size(); j++) {
- if(i == j)
- continue;
- if( DomUtils.isAncestorOf(candidates.get(j), candidates.get(i), true) ) {
- skip = true;
- break;
- }
- }
- if(!skip) {
- unnesteds.add( candidates.get(i) );
- }
- }
- return unnesteds;
- }
-
public void setErrorMode(ErrorMode errorMode) {
if(errorMode == null)
throw new IllegalArgumentException("errorMode must be not null.");
@@ -527,35 +501,42 @@ public class MicrodataParser {
public List<ItemProp> getItemProps(final Node scopeNode, boolean skipRoot) throws MicrodataParserException {
final Set<Node> accepted = new LinkedHashSet<>();
+ boolean skipRootChildren = false;
if (!skipRoot) {
NamedNodeMap attributes = scopeNode.getAttributes();
if (attributes.getNamedItem(ITEMPROP_ATTRIBUTE) != null) {
accepted.add(scopeNode);
}
+ if (attributes.getNamedItem(ITEMSCOPE_ATTRIBUTE) != null) {
+ skipRootChildren = true;
+ }
}
- // TreeWalker to walk DOM tree starting with the scopeNode. Nodes maybe visited multiple times.
- TreeWalker treeWalker = ((DocumentTraversal) scopeNode.getOwnerDocument())
- .createTreeWalker(scopeNode, NodeFilter.SHOW_ELEMENT, new NodeFilter() {
- @Override
- public short acceptNode(Node node) {
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- NamedNodeMap attributes = node.getAttributes();
- if (attributes.getNamedItem(ITEMPROP_ATTRIBUTE) != null && !scopeNode.equals(node)) {
- accepted.add(node);
- }
+ if (!skipRootChildren) {
+ // TreeWalker to walk DOM tree starting with the scopeNode. Nodes maybe visited multiple times.
+ TreeWalker treeWalker = ((DocumentTraversal) scopeNode.getOwnerDocument())
+ .createTreeWalker(scopeNode, NodeFilter.SHOW_ELEMENT, new NodeFilter() {
+ @Override
+ public short acceptNode(Node node) {
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ NamedNodeMap attributes = node.getAttributes();
+ if (attributes.getNamedItem(ITEMPROP_ATTRIBUTE) != null && !scopeNode.equals(node)) {
+ accepted.add(node);
+ }
+
+ if (attributes.getNamedItem(ITEMSCOPE_ATTRIBUTE) != null) {
+ // Don't visit descendants of nodes that define a new scope
+ return FILTER_REJECT;
+ }
+ }
+ return FILTER_ACCEPT;
+ }
+ }, false);
- if (attributes.getNamedItem(ITEMSCOPE_ATTRIBUTE) != null) {
- // Don't visit descendants of nodes that define a new scope
- return FILTER_REJECT;
- }
- }
- return FILTER_ACCEPT;
- }
- }, false);
- // To populate accepted we only need to walk the tree.
- while (treeWalker.nextNode() != null);
+ // To populate accepted we only need to walk the tree.
+ while (treeWalker.nextNode() != null) ;
+ }
final List<ItemProp> result = new ArrayList<>();
for (Node itemPropNode : accepted) {
http://git-wip-us.apache.org/repos/asf/any23/blob/2175c2d3/core/src/test/java/org/apache/any23/extractor/microdata/MicrodataExtractorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/any23/extractor/microdata/MicrodataExtractorTest.java b/core/src/test/java/org/apache/any23/extractor/microdata/MicrodataExtractorTest.java
index 11aa353..0e634de 100644
--- a/core/src/test/java/org/apache/any23/extractor/microdata/MicrodataExtractorTest.java
+++ b/core/src/test/java/org/apache/any23/extractor/microdata/MicrodataExtractorTest.java
@@ -197,6 +197,7 @@ public class MicrodataExtractorTest extends AbstractExtractorTestCase {
TreeModel actual = new TreeModel();
createRunner(MicrodataExtractorFactory.NAME).extract(action.stringValue(), new TripleWriterHandler() {
public void writeTriple(Resource s, IRI p, Value o, Resource g) {
+ if (MicrodataExtractor.MICRODATA_ITEM.equals(p)) return;
actual.add(s, p, o);
}
public void writeNamespace(String prefix, String uri) { }
@@ -214,8 +215,7 @@ public class MicrodataExtractorTest extends AbstractExtractorTestCase {
});
}
- boolean testPassed = positive ? (expected.isEmpty() ? actual.isEmpty()
- : Models.isSubset(expected, actual)) : !Models.isomorphic(expected, actual);
+ boolean testPassed = positive == Models.isomorphic(expected, actual);
if (testPassed) {
passedTests.incrementAndGet();
} else {
http://git-wip-us.apache.org/repos/asf/any23/blob/2175c2d3/test-resources/src/test/resources/microdata/5.2.1-non-normative-example-2-expected.nquads
----------------------------------------------------------------------
diff --git a/test-resources/src/test/resources/microdata/5.2.1-non-normative-example-2-expected.nquads b/test-resources/src/test/resources/microdata/5.2.1-non-normative-example-2-expected.nquads
index b3e99b0..8eedf33 100644
--- a/test-resources/src/test/resources/microdata/5.2.1-non-normative-example-2-expected.nquads
+++ b/test-resources/src/test/resources/microdata/5.2.1-non-normative-example-2-expected.nquads
@@ -16,7 +16,6 @@
#
_:nodebdb2c525cf8095abb6954b51432e6 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://microformats.org/profile/hcard> <http://bob.example.com/> .
-_:nodebdb2c525cf8095abb6954b51432e6 <http://microformats.org/profile/hcard#street-address> "Avenue Q" <http://bob.example.com/> .
_:nodebdb2c525cf8095abb6954b51432e6 <http://microformats.org/profile/hcard#fn> "Princeton" <http://bob.example.com/> .
_:nodebdb2c525cf8095abb6954b51432e6 <http://microformats.org/profile/hcard#given-name> "Princeton" <http://bob.example.com/> .
_:nodebdb2c525cf8095abb6954b51432e6 <http://microformats.org/profile/hcard#n> _:node5194c3bb9d7f53e4759c6f393d95f88 <http://bob.example.com/> .
@@ -24,7 +23,6 @@ _:node1ffeb2699b75ba7aca5ee3d72adb55a8 <http://microformats.org/profile/hcard#st
_:nodebdb2c525cf8095abb6954b51432e6 <http://microformats.org/profile/hcard#adr> _:node1ffeb2699b75ba7aca5ee3d72adb55a8 <http://bob.example.com/> .
<http://bob.example.com/> <http://www.w3.org/1999/xhtml/microdata#item> _:nodebdb2c525cf8095abb6954b51432e6 <http://bob.example.com/> .
_:node7a12e48e321d29211c8b7c2ce396854 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://microformats.org/profile/hcard> <http://bob.example.com/> .
-_:node7a12e48e321d29211c8b7c2ce396854 <http://microformats.org/profile/hcard#street-address> "Avenue Q" <http://bob.example.com/> .
_:node7a12e48e321d29211c8b7c2ce396854 <http://microformats.org/profile/hcard#fn> "Trekkie" <http://bob.example.com/> .
_:node7a12e48e321d29211c8b7c2ce396854 <http://microformats.org/profile/hcard#given-name> "Trekkie" <http://bob.example.com/> .
_:node7a12e48e321d29211c8b7c2ce396854 <http://microformats.org/profile/hcard#n> _:node45173ea18b736c2e9c3136e52ed3727e <http://bob.example.com/> .