Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method to rename an Element's Tag without resetting the tag's properties #1980

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/main/java/org/jsoup/nodes/Element.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ public Element tagName(String tagName) {
return this;
}

/**
* Change (rename) the tag of this element. For example, convert a {@code <span>} to a {@code <div>} with
* {@code el.tagName("div");}.
*
* @param tagName new tag name for this element
* @return this element, for chaining
* @see Elements#tagName(String)
*/
public Element renameTagPreserveProperties(String tagName) {
Validate.notEmptyParam(tagName, "tagName");
tag = Tag.convertTag(tag, tagName); // maintains the case option of the original parse
return this;
}

/**
* Get the Tag for this element.
*
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/org/jsoup/parser/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@ public static Tag valueOf(String tagName, ParseSettings settings) {
return tag;
}

/**
* Create a new tag with a new name, copying the same characteristics as the old one.
*
* @param tagName Name of tag, e.g. "p". Case insensitive.
* @return The tag, either defined or new generic.
*/
public static Tag convertTag(Tag oldTag, String tagName) {
Validate.notNull(tagName);
Tag tag = new Tag(tagName);
tag.empty = oldTag.empty;
tag.formList = oldTag.formList;
tag.formSubmit = oldTag.formSubmit;
tag.formatAsBlock = oldTag.formatAsBlock;
tag.isBlock = oldTag.isBlock;
tag.preserveWhitespace = oldTag.preserveWhitespace;
tag.selfClosing = oldTag.selfClosing;

return tag;
}

/**
* Get a Tag by name. If not previously defined (unknown), returns a new generic tag, that can do anything.
* <p>
Expand Down
33 changes: 33 additions & 0 deletions src/test/java/org/jsoup/nodes/ElementTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,39 @@ public void testTagNameSet() {
assertEquals("<em>Hello</em>", doc.select("div").first().html());
}

@Test
public void tagNameChangeResetsProperties() {
Document doc = Jsoup.parse("<img src='foo.png'>");
Element img = doc.select("img").first();

assertTrue(img.tag().isInline());
assertTrue(img.tag().isSelfClosing());
assertFalse(img.isBlock());

// When we rename a tag to a new, unregistered name, confirm that its properties are reset, just as if
// we had created one from scratch.

Tag testTag = Tag.valueOf("jspControl:image", NodeUtils.parser(doc).settings());
img.tagName("jspControl:image");
assertEquals(testTag, img.tag());
}

@Test
public void testRenameTagPreserveProperties() {
Document doc = Jsoup.parse("<img src='foo.png'>");
Element img = doc.select("img").first();
assertTrue(img.tag().isInline());
assertTrue(img.tag().isSelfClosing());
assertFalse(img.isBlock());

// When we rename to an unrecognized tag, but tell the element to keep its tag properties, the previous
// assertions should still hold true.
img.renameTagPreserveProperties("jspControl:image");
assertTrue(img.tag().isInline());
assertTrue(img.tag().isSelfClosing());
assertFalse(img.isBlock());
}

@Test
public void testHtmlContainsOuter() {
Document doc = Jsoup.parse("<title>Check</title> <div>Hello there</div>");
Expand Down